public async Task RollbackWithoutRequestsShouldNotGenerateMessage() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{'statements': []}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { rollbackTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(initTransactionRequest, rollbackTransactionRequest)) { var client = await testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // no requests await transaction.RollbackAsync(); } } }
public void UpdateTransactionEndpointAfterFirstRequest() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { rollbackTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); Assert.AreEqual( new Uri("http://foo/db/data/transaction/1"), ((INeo4jTransaction)((TransactionScopeProxy)transaction).TransactionContext).Endpoint); } } }
public void OnTransactionDisposeCallRollback() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { rollbackTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); } } }
public async Task UsesTheSetDatabase() { const string database = "neo4jclient"; var initTransactionRequest = MockRequest.PostJson($"/db/{database}/tx", "{'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete($"/db/{database}/tx/1"); var commitTransactionRequest = MockRequest.PostJson($"/db/{database}/tx/1/commit", EmptyStatements); var keepAliveTransactionRequest = MockRequest.PostJson($"/db/{database}/tx/1", EmptyStatements); using (var testHarness = new RestTestHarness(false, "http://foo:7474") { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), $"http://foo:7474/db/{database}/tx/1") }, { commitTransactionRequest, EmptyOkResponse }, { rollbackTransactionRequest, EmptyOkResponse }, { keepAliveTransactionRequest, EmptyOkResponse } }) { var client = await testHarness.CreateAndConnectTransactionalGraphClient(RestTestHarness.Neo4jVersion.Neo40); using (var transaction = client.BeginTransaction(TransactionScopeOption.Join, null, database)) { // dummy query to generate request await client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResultsAsync().ConfigureAwait(false); await transaction.KeepAliveAsync(); } } }
//https://github.com/Readify/Neo4jClient/issues/127 public async Task ReturnsThe404_WhenVersionIs_2_2_6_Plus_WhenActuallyTimingOut(RestTestHarness.Neo4jVersion version) { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness() { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { rollbackTransactionRequest, MockResponse.Json(404, "{\"results\":[],\"errors\":[{\"code\":\"Neo.ClientError.Transaction.UnknownId\",\"message\":\"Unrecognized transaction id. Transaction may have timed out and been rolled back.\"}]}") } }) { var client = testHarness.CreateGraphClient(version); await client.ConnectAsync(); try { using (var transaction = client.BeginTransaction()) { await client.Cypher.Match("n").Return(n => n.Count()).ExecuteWithoutResultsAsync(); } throw new Exception("Should not reach this code, as there is an expected exception."); } catch (Exception ex) { Assert.True(ex.Message.Contains("404")); } } }
//https://github.com/Readify/Neo4jClient/issues/127 public async Task ReturnsCorrectError_WhenTransactionIsAutomaticallyRolledBack_ViaNeo4j_2_2_6_Plus(RestTestHarness.Neo4jVersion version) { /* In 2.2.6 ClientErrors (Constraint Violations etc) were changed to Automatically rollback. This created a 404 error when *we* tried to rollback on an error, as the transaction no longer existed. */ var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateCypherErrorResponse(1, "{\"code\":\"Neo.ClientError.Schema.ConstraintViolation\",\"message\":\"Node 19572 already exists with label User and property.\"}"), "http://foo/db/data/transaction/1") }, { rollbackTransactionRequest, MockResponse.Json(404, "{\"results\":[],\"errors\":[{\"code\":\"Neo.ClientError.Transaction.UnknownId\",\"message\":\"Unrecognized transaction id. Transaction may have timed out and been rolled back.\"}]}") } }) { var client = testHarness.CreateGraphClient(version); await client.ConnectAsync(); using (var transaction = client.BeginTransaction()) { await Assert.ThrowsAsync <NeoException>(async() => await client.Cypher.Match("n").Return(n => n.Count()).ExecuteWithoutResultsAsync()); } } }
public void TransactionRollbackInTransactionScope() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var deleteRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var scope = new TransactionScope()) { client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); } } }
//https://github.com/Readify/Neo4jClient/issues/127 public async Task ReturnsThe404_WhenVersionIsLessThan_2_2_6(RestTestHarness.Neo4jVersion version) { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateCypherErrorResponse(1, "{\"code\":\"Neo.ClientError.Schema.ConstraintViolation\",\"message\":\"Node 19572 already exists with label User and property.\"}"), "http://foo/db/data/transaction/1") }, { rollbackTransactionRequest, MockResponse.Json(404, "{\"results\":[],\"errors\":[{\"code\":\"Neo.ClientError.Transaction.UnknownId\",\"message\":\"Unrecognized transaction id. Transaction may have timed out and been rolled back.\"}]}") } }) { var client = testHarness.CreateGraphClient(version); await client.ConnectAsync(); try { using (var transaction = client.BeginTransaction()) { await client.Cypher.Match("n").Return(n => n.Count()).ExecuteWithoutResultsAsync(); } } catch (Exception ex) { Assert.True(ex.Message.Contains("404")); } } }
public void NestedTransactionMixedBetweenTransactionScopeAndBeginTransaction() { const string queryText = @"MATCH (n) RETURN count(n)"; const string resultColumn = @"{'columns':['count(n)'], 'data':[{'row':[1]}]}"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery, false) }; var deleteRequest = MockRequest.Delete("/transaction/1"); var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(commitRequest)) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var parentTx = client.BeginTransaction()) { using (var msTransaction = new TransactionScope()) { Assert.IsTrue(client.InTransaction); using (var tx = client.BeginTransaction()) { long total = client.Cypher .Match("(n)") .Return(n => n.Count()) .Results .SingleOrDefault(); Assert.AreEqual(1, total); // should not be called tx.Commit(); } msTransaction.Complete(); } } Assert.IsFalse(client.InTransaction); } }
public void SuppressTransactionScopeShouldNotEmitTransactionalQuery() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var nonTransactionalRequest = MockRequest.PostJson("/cypher", @"{'query': 'MATCH n\r\nRETURN count(n)', 'params': {}}"); var commitTransactionRequest = MockRequest.PostJson("/transaction/1/commit", @"{ 'statements': []}"); var deleteRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { nonTransactionalRequest, MockResponse.Json(200, @"{'columns':['count(n)'], 'data':[[0]] }") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(deleteRequest)) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = new TransactionScope()) { using (var tran2 = new TransactionScope(TransactionScopeOption.Suppress)) { client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); // no rollback should be generated } client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); tran.Complete(); } } }
public void ShouldDeleteNodeOnly() { using (var testHarness = new RestTestHarness { { MockRequest.Delete("/node/456"), MockResponse.Http(204) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); graphClient.Delete(456, DeleteMode.NodeOnly); } }
public void ShouldThrowApplicationExceptionWhenDeleteFails() { using (var testHarness = new RestTestHarness { { MockRequest.Delete("/relationship/456"), MockResponse.Http(404) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); graphClient.DeleteRelationship(456); } }
public void ShouldThrowApplicationExceptionWhenDeleteFails() { using (var testHarness = new RestTestHarness { { MockRequest.Delete("/node/456"), MockResponse.Http(409) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); graphClient.Delete(456, DeleteMode.NodeOnly); } }
public void ShouldDeleteRelationship() { using (var testHarness = new RestTestHarness { { MockRequest.Delete("/relationship/456"), MockResponse.Http(204) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); graphClient.DeleteRelationship(456); } }
public void ShouldThrowExceptionWhenDeleteFails() { using (var testHarness = new RestTestHarness { { MockRequest.Delete("/node/456"), MockResponse.Http(409) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); var ex = Assert.Throws <Exception>(() => graphClient.Delete(456, DeleteMode.NodeOnly)); ex.Message.Should().Be("Unable to delete the node. The node may still have relationships. The response status was: 409 Conflict"); } }
public void ShouldThrowExceptionWhenDeleteFails() { using (var testHarness = new RestTestHarness { { MockRequest.Delete("/relationship/456"), MockResponse.Http(404) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); var ex = Assert.Throws <Exception>(() => graphClient.DeleteRelationship(456)); ex.Message.Should().Be("Unable to delete the relationship. The response status was: 404 NotFound"); } }
public void ShouldExecuteSilentlyForSuccessfulDelete() { using (var testHarness = new RestTestHarness { { MockRequest.Delete("/index/node/MyIndex"), MockResponse.Http(204) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); //Act graphClient.DeleteIndex("MyIndex", IndexFor.Node); } }
public void NestedJoinedTransactionScope() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var secondRequest = MockRequest.PostJson("/transaction/1", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var deleteRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { secondRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var scope = new TransactionScope()) { using (var scope2 = new TransactionScope()) { client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); // this will not commit scope2.Complete(); } // this should generate a request to the known transaction ID client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); } } }
public void ShouldPreserveSlashInRelationshipIndexValue() { //Arrange var indexKeyValues = new Dictionary <string, object> { { "BarKey", "abc/def" } }; var indexEntries = new List <IndexEntry> { new IndexEntry { Name = "my_relationships", KeyValues = indexKeyValues, } }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/index/relationship/my_relationships", new { key = "BarKey", value = "abc/def", uri = "http://foo/db/data/relationship/123" }), MockResponse.Json(HttpStatusCode.Created, @"Location: http://foo/db/data/index/relationship/my_relationships/BarKey/abc-def/1234") }, { MockRequest.Delete("/index/relationship/my_relationships/123"), MockResponse.Http((int)HttpStatusCode.NoContent) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); //Act var relReference = new RelationshipReference(123); graphClient.ReIndex(relReference, indexEntries); // Assert Assert.Pass("Success."); } }
public void ShouldDeleteAllRelationshipsFirst() { using (var testHarness = new RestTestHarness { { MockRequest.Get("/node/456/relationships/all"), MockResponse.Json(HttpStatusCode.OK, @"[ { 'self': 'http://foo/db/data/relationship/56', 'start': 'http://foo/db/data/node/123', 'end': 'http://foo/db/data/node/456', 'type': 'KNOWS', 'properties': 'http://foo/db/data/relationship/56/properties', 'property': 'http://foo/db/data/relationship/56/properties/{key}', 'data': { 'date': 1270559208258 } }, { 'self': 'http://foo/db/data/relationship/78', 'start': 'http://foo/db/data/node/456', 'end': 'http://foo/db/data/node/789', 'type': 'KNOWS', 'properties': 'http://foo/db/data/relationship/78/properties', 'property': 'http://foo/db/data/relationship/78/properties/{key}', 'data': { 'date': 1270559208258 } } ]") }, { MockRequest.Delete("/relationship/56"), MockResponse.Http(204) }, { MockRequest.Delete("/relationship/78"), MockResponse.Http(204) }, { MockRequest.Delete("/node/456"), MockResponse.Http(204) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); graphClient.Delete(456, DeleteMode.NodeAndRelationships); } }
public void ShouldAcceptQuestionMarkInIndexValue() { //Arrange var indexKeyValues = new Dictionary <string, object> { { "FooKey", "foo?bar" } }; var indexEntries = new List <IndexEntry> { new IndexEntry { Name = "my_nodes", KeyValues = indexKeyValues, } }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/index/node/my_nodes", new { key = "FooKey", value = "foo?bar", uri = "http://foo/db/data/node/123" }), MockResponse.Json(HttpStatusCode.Created, @"Location: http://foo/db/data/index/node/my_nodes/FooKey/%3f/123") }, { MockRequest.Delete("/index/node/my_nodes/123"), MockResponse.Http((int)HttpStatusCode.NoContent) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); //Act graphClient.ReIndex((NodeReference)123, indexEntries); // Assert Assert.Pass("Success."); } }
public void ShouldReindexRelationshipWithDateTimeOffsetIndexEntry() { //Arrange var indexEntries = new List <IndexEntry> { new IndexEntry { Name = "my_relationships", KeyValues = new Dictionary <string, object> { { "BarKey", new DateTimeOffset(1000, new TimeSpan(0)) } }, } }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/index/relationship/my_relationships", new { key = "BarKey", value = "1000", uri = "http://foo/db/data/relationship/1234" }), MockResponse.Json(HttpStatusCode.Created, @"Location: http://foo/db/data/index/relationship/my_relationships/BarKey/someDateValue/1234") }, { MockRequest.Delete("/index/relationship/my_relationships/1234"), MockResponse.Http((int)HttpStatusCode.NoContent) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); //Act var relReference = new RelationshipReference(1234); graphClient.ReIndex(relReference, indexEntries); // Assert Assert.Pass("Success."); } }
public async Task DeserializeResultsFromTransaction() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var deserializationRequest = MockRequest.PostJson("/transaction/1", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { deserializationRequest, MockResponse.Json(200, @"{'results':[{'columns': ['count(n)'], 'data': [{'row': [0]}]}]}") }, { rollbackTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = await testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request await client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResultsAsync(); // this query will hit the deserializer var count = await client.Cypher .Match("n") .Return(n => n.Count()) .ResultsAsync; Assert.Equal(count.First(), 0); } } }
public void ShouldReindexRelationshipWithIndexEntryContainingSpace() { //Arrange var indexEntries = new List <IndexEntry> { new IndexEntry { Name = "my_relationships", KeyValues = new Dictionary <string, object> { { "BarKey", "the_value with space" } }, } }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/index/relationship/my_relationships", new { key = "BarKey", value = "the_value with space", uri = "http://foo/db/data/relationship/1234" }), MockResponse.Json(HttpStatusCode.Created, @"Location: http://foo/db/data/index/relationship/my_relationships/BarKey/the_value%20with%20space/1234") }, { MockRequest.Delete("/index/relationship/my_relationships/1234"), MockResponse.Http((int)HttpStatusCode.NoContent) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); //Act var relReference = new RelationshipReference(1234); graphClient.ReIndex(relReference, indexEntries); // Assert } }
public void ShouldReindexNodeWithDateTimeOffsetIndexEntry() { //Arrange var indexEntries = new List <IndexEntry> { new IndexEntry { Name = "my_nodes", KeyValues = new Dictionary <string, object> { { "FooKey", new DateTimeOffset(1000, new TimeSpan(0)) } }, } }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/index/node/my_nodes", new { key = "FooKey", value = "1000", uri = "http://foo/db/data/node/123" }), MockResponse.Json(HttpStatusCode.Created, @"Location: http://foo/db/data/index/node/my_nodes/FooKey/someDateValue/123") }, { MockRequest.Delete("/index/node/my_nodes/123"), MockResponse.Http((int)HttpStatusCode.NoContent) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); //Act graphClient.ReIndex((NodeReference)123, indexEntries); // Assert } }
public void ShouldReplaceNodeWithIndexEntries() { var newData = new TestNode { Foo = "foo", Bar = "bar", Baz = "baz" }; using (var testHarness = new RestTestHarness { { MockRequest.PutObjectAsJson("/node/456/properties", newData), MockResponse.Http((int)HttpStatusCode.NoContent) }, { MockRequest.Delete("/index/node/foo/456"), MockResponse.Http((int)HttpStatusCode.NoContent) }, { MockRequest.PostObjectAsJson("/index/node/foo", new { key = "foo", value = "bar", uri = "http://foo/db/data/node/456" }), MockResponse.Json(HttpStatusCode.Created, "Location: http://foo/db/data/index/node/foo/bar/456") } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); // Act var pocoReference = new NodeReference <TestNode>(456); graphClient.Update( pocoReference, newData, new [] { new IndexEntry { Name = "foo", KeyValues = new Dictionary <string, object> { { "foo", "bar" } }, } }); } }
public void ShouldUpdateNodeWithIndexEntries() { var nodeToUpdate = new TestNode { Foo = "foo", Bar = "bar", Baz = "baz" }; using (var testHarness = new RestTestHarness { { MockRequest.Get("/node/456"), MockResponse.Json(HttpStatusCode.OK, @"{ 'self': 'http://foo/db/data/node/456', 'data': { 'Foo': 'foo', 'Bar': 'bar', 'Baz': 'baz' }, 'create_relationship': 'http://foo/db/data/node/456/relationships', 'all_relationships': 'http://foo/db/data/node/456/relationships/all', 'all_typed relationships': 'http://foo/db/data/node/456/relationships/all/{-list|&|types}', 'incoming_relationships': 'http://foo/db/data/node/456/relationships/in', 'incoming_typed relationships': 'http://foo/db/data/node/456/relationships/in/{-list|&|types}', 'outgoing_relationships': 'http://foo/db/data/node/456/relationships/out', 'outgoing_typed relationships': 'http://foo/db/data/node/456/relationships/out/{-list|&|types}', 'properties': 'http://foo/db/data/node/456/properties', 'property': 'http://foo/db/data/node/456/property/{key}', 'traverse': 'http://foo/db/data/node/456/traverse/{returnType}' }") }, { MockRequest.PutObjectAsJson("/node/456/properties", nodeToUpdate), MockResponse.Http((int)HttpStatusCode.NoContent) }, { MockRequest.Delete("/index/node/foo/456"), MockResponse.Http((int)HttpStatusCode.NoContent) }, { MockRequest.PostObjectAsJson("/index/node/foo", new { key = "foo", value = "bar", uri = "http://foo/db/data/node/456" }), MockResponse.Json(HttpStatusCode.Created, "Location: http://foo/db/data/index/node/foo/bar/456") } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); // Act var pocoReference = new NodeReference <TestNode>(456); graphClient.Update( pocoReference, nodeFromDb => { nodeFromDb.Foo = "fooUpdated"; nodeFromDb.Baz = "bazUpdated"; nodeToUpdate = nodeFromDb; }, nodeFromDb => new List <IndexEntry> { new IndexEntry { Name = "foo", KeyValues = new Dictionary <string, object> { { "foo", "bar" } }, } }); Assert.AreEqual("fooUpdated", nodeToUpdate.Foo); Assert.AreEqual("bazUpdated", nodeToUpdate.Baz); Assert.AreEqual("bar", nodeToUpdate.Bar); } }