Skip to content

m00ndark/net-mock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

56 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status NuGet Badge

net-mock

NetMock is a .NET network service mock framework, inspired by Moq syntax, providing the ability to mock REST and web socket APIs from within a test framework of choice.

Examples

A set of examples to show usage and possibilities are part of the solution, available here.

Status

The following table shows the implementation status of currenly planned features.

Service mock

Component Feature Status
Configuration ActivationStrategy { Manual, AutomaticOnCreation } (default is AutomaticOnCreation)
  MockBehavior { Loose, Strict } (default is Loose)
  PrintReceivedRequestsOnTearDown (default is false)
Mock creation CreateRestMock(int port, MockBehavior mockBehavior)
  CreateRestMock(string basePath, int port, MockBehavior mockBehavior)
  CreateSecureRestMock(int port, X509FindType certificateFindType, string certificateFindValue, StoreName storeName, StoreLocation storeLocation, MockBehavior mockBehavior)
  CreateSecureRestMock(string basePath, int port, X509FindType certificateFindType, string certificateFindValue, StoreName storeName, StoreLocation storeLocation, MockBehavior mockBehavior)
  CreateSecureRestMock(int port, X509Certificate2 certificate, MockBehavior mockBehavior)
  CreateSecureRestMock(string basePath, int port, X509Certificate2 certificate, MockBehavior mockBehavior)

REST mock

Component Feature Status
HTTP methods Get , Post , Put , Delete , Head , Options , Trace , Connect
Configuration StaticHeaders
  DefaultResponseStatusCode (default is NotImplemented)
  UndefinedQueryParameterHandling { Ignore, Fail } (default is Fail)
  UndefinedHeaderHandling { Ignore, Fail } (default is Ignore)
  MockBehavior { Loose, Strict } (default is Loose)
  InterpretBodyAsJson (default is true)
Request setup Setup(Method method, string path, params IMatch[] matches)
  SetupGet(string path, params IMatch[] matches)
  SetupPost(string path, params IMatch[] matches)
  SetupPut(string path, params IMatch[] matches)
  SetupDelete(string path, params IMatch[] matches)
  SetupHead(string path, params IMatch[] matches)
  SetupOptions(string path, params IMatch[] matches)
  SetupTrace(string path, params IMatch[] matches)
  SetupConnect(string path, params IMatch[] matches)
Request verification Verify(Method method, string path, params IMatch[] matches, Times times)
  VerifyGet(string path, params IMatch[] matches, Times times)
  VerifyPost(string path, params IMatch[] matches, Times times)
  VerifyPut(string path, params IMatch[] matches, Times times)
  VerifyDelete(string path, params IMatch[] matches, Times times)
  VerifyHead(string path, params IMatch[] matches, Times times)
  VerifyOptions(string path, params IMatch[] matches, Times times)
  VerifyTrace(string path, params IMatch[] matches, Times times)
  VerifyConnect(string path, params IMatch[] matches, Times times)
Response setup Returns(params AttachedHeader[] headers)
  Returns(int statusCode, params AttachedHeader[] headers)
  Returns(HttpStatusCode statusCode, params AttachedHeader[] headers)
  Returns(object body, params AttachedHeader[] headers)
  Returns(int statusCode, object body, params AttachedHeader[] headers)
  Returns(HttpStatusCode statusCode, object body, params AttachedHeader[] headers)
  Returns(Func<int> statusCodeProvider)
  Returns(Func<IReceivedRequest, int> statusCodeProvider)
  Returns(Func<HttpStatusCode> statusCodeProvider)
  Returns(Func<IReceivedRequest, HttpStatusCode> statusCodeProvider)
  Returns(Func<object> bodyProvider)
  Returns(Func<IReceivedRequest, object> bodyProvider)
  Returns(Func<IEnumerable<AttachedHeader>> headersProvider)
  Returns(Func<IReceivedRequest, IEnumerable<AttachedHeader>> headersProvider)
  Returns(Func<(int StatusCode, object Body)> responseProvider)
  Returns(Func<IReceivedRequest, (int StatusCode, object Body)> responseProvider)
  Returns(Func<(HttpStatusCode StatusCode, object Body)> responseProvider)
  Returns(Func<IReceivedRequest, (HttpStatusCode StatusCode, object Body)> responseProvider)
  Returns(Func<(int StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns(Func<IReceivedRequest, (int StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns(Func<(HttpStatusCode StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns(Func<IReceivedRequest, (HttpStatusCode StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns(Func<(object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns(Func<IReceivedRequest, (object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns<T1>(Func<T1, int> statusCodeProvider)
  Returns<T1>(Func<IReceivedRequest, T1, int> statusCodeProvider)
  Returns<T1>(Func<T1, HttpStatusCode> statusCodeProvider)
  Returns<T1>(Func<IReceivedRequest, T1, HttpStatusCode> statusCodeProvider)
  Returns<T1>(Func<T1, object> bodyProvider)
  Returns<T1>(Func<IReceivedRequest, T1, object> bodyProvider)
  Returns<T1>(Func<T1, IEnumerable<AttachedHeader>> headersProvider)
  Returns<T1>(Func<IReceivedRequest, T1, IEnumerable<AttachedHeader>> headersProvider)
  Returns<T1>(Func<T1, (int StatusCode, object Body)> responseProvider)
  Returns<T1>(Func<IReceivedRequest, T1, (int StatusCode, object Body)> responseProvider)
  Returns<T1>(Func<T1, (HttpStatusCode StatusCode, object Body)> responseProvider)
  Returns<T1>(Func<IReceivedRequest, T1, (HttpStatusCode StatusCode, object Body)> responseProvider)
  Returns<T1>(Func<T1, (int StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns<T1>(Func<IReceivedRequest, T1, (int StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns<T1>(Func<T1, (HttpStatusCode StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns<T1>(Func<IReceivedRequest, T1, (HttpStatusCode StatusCode, object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns<T1>(Func<T1, (object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Returns<T1>(Func<IReceivedRequest, T1, (object Body, IEnumerable<AttachedHeader> Headers)> responseProvider)
  Above generic signatures with generic arguments ranging up to T9 (additional 144 overloads)
  Callback(Action callback)
  Callback(Action<IReceivedRequest> callback)
  Callback<T1>(Action<T1> callback)
  Callback<T1>(Action<IReceivedRequest, T1> callback)
  Above generic signatures with generic arguments ranging up to T9 (additional 16 overloads)
Parameter matching Parameter.Is<TValue>(string name, TValue value)
  Parameter.Is<TValue>(string name, TValue value, CompareCase compareCase)
  Parameter.Is(string name, Func<string, bool> condition)
  Parameter.Is<TValue>(string name, Func<TValue, bool> condition)
  Parameter.IsNot<TValue>(string name, TValue value)
  Parameter.IsNot<TValue>(string name, TValue value, CompareCase compareCase)
  Parameter.IsAny(string name)
  Parameter.IsAny<TValue>(string name)
  Parameter.StartsWith<TValue>(string name, TValue value)
  Parameter.StartsWith<TValue>(string name, TValue value, CompareCase compareCase)
  Parameter.EndsWith<TValue>(string name, TValue value)
  Parameter.EndsWith<TValue>(string name, TValue value, CompareCase compareCase)
  Parameter.Contains<TValue>(string name, TValue value)
  Parameter.Contains<TValue>(string name, TValue value, CompareCase compareCase)
  Parameter.NotContains<TValue>(string name, TValue value)
  Parameter.NotContains<TValue>(string name, TValue value, CompareCase compareCase)
  Parameter.StartsWithWord<TValue>(string name, TValue word)
  Parameter.StartsWithWord<TValue>(string name, TValue word, CompareCase compareCase)
  Parameter.EndsWithWord<TValue>(string name, TValue word)
  Parameter.EndsWithWord<TValue>(string name, TValue word, CompareCase compareCase)
  Parameter.ContainsWord<TValue>(string name, TValue word)
  Parameter.ContainsWord<TValue>(string name, TValue word, CompareCase compareCase)
  Parameter.NotContainsWord<TValue>(string name, TValue word)
  Parameter.NotContainsWord<TValue>(string name, TValue word, CompareCase compareCase)
Header matching Header.Is<TValue>(string name, TValue value)
  Header.Is<TValue>(string name, TValue value, CompareCase compareCase)
  Header.Is(string name, Func<string, bool> condition)
  Header.Is<TValue>(string name, Func<TValue, bool> condition)
  Header.IsNot<TValue>(string name, TValue value)
  Header.IsNot<TValue>(string name, TValue value, CompareCase compareCase)
  Header.IsSet(string name)
  Header.IsNotSet(string name)
  Header.Contains<TValue>(string name, TValue value)
  Header.Contains<TValue>(string name, TValue value, CompareCase compareCase)
  Header.NotContains<TValue>(string name, TValue value)
  Header.NotContains<TValue>(string name, TValue value, CompareCase compareCase)
Body matching Body.Is<TValue>(TValue value)
  Body.Is<TValue>(TValue value, CompareCase compareCase)
  Body.Is(Func<string, bool> condition)
  Body.Is<TValue>(Func<TValue, bool> condition)
  Body.IsNot<TValue>(TValue value)
  Body.IsNot<TValue>(TValue value, CompareCase compareCase)
  Body.IsAny()
  Body.IsAny<TValue>()
  Body.IsEmpty()
  Body.IsNotEmpty()
  Body.Contains<TValue>(TValue value)
  Body.Contains<TValue>(TValue value, CompareCase compareCase)
  Body.NotContains<TValue>(TValue value)
  Body.NotContains<TValue>(TValue value, CompareCase compareCase)
  Body.ContainsWord<TValue>(TValue word)
  Body.ContainsWord<TValue>(TValue word, CompareCase compareCase)
  Body.NotContainsWord<TValue>(TValue word)
  Body.NotContainsWord<TValue>(TValue word, CompareCase compareCase)
Verification hit count matching Times.Never
  Times.Once
  Times.Twice
  Times.AtLeastOnce
  Times.AtMostOnce
  Times.Exactly(int callCount)
  Times.AtLeast(int callCount)
  Times.AtMost(int callCount)
  Times.Between(int callCountFrom, int callCountTo)

Web socket mock

No implementation started.

Inspiration

// arrange
ServiceMock serviceMock = new ServiceMock();
RestMock restMock = serviceMock.CreateRestMock("/api/v1", 9001, useSSL: false);
restMock.Setup(Method.Get, "/alive").Returns(new AliveMessage());
serviceMock.Activate();

// act
...

// assert
restMock.Verify(Method.Get, "/alive", Times.Once);

// teardown
serviceMock.Teardown();
// arrange
ServiceMock serviceMock = new ServiceMock();
serviceMock.InstallCerts(certFile);
RestMock restMock = serviceMock.CreateRestMock("/api/v1", 9001, useSSL: true);
restMock.Setup(Method.Post, "/user", body: new User() { UserId = "abc" })
        .Returns(new User() { ID = new Guid("698fa58a-8e9c-4607-b6c3-b5da19751a04"), UserId = "abc" });
serviceMock.Activate();

// act
...

// assert
restMock.Verify(Method.Post, "/user", Times.Once)

// teardown
serviceMock.Teardown();
// arrange
ServiceMock serviceMock = new ServiceMock();
serviceMock.InstallCerts(certFile);
RestMock restMock = serviceMock.CreateRestMock("/api/v1", 9001, useSSL: true);
restMock.Setup(Method.Post, "/user", body: "{ 'userId' = 'abc' }")
        .Returns("{ 'id' = '698fa58a-8e9c-4607-b6c3-b5da19751a04', 'userId' = 'abc' }");
restMock.Setup(Method.Post, "/user", body: "{ 'userId' = 'xyz' }")
        .Returns("{ 'id' = '607a755d-3ded-4a42-9a96-03d9ecfd31da', 'userId' = 'xyz' }");
serviceMock.Activate();

// act
...

// assert
restMock.Verify(Method.Post, "/user", Times.Twice);
restMock.Verify(Method.Post, "/user", body: "{ 'userId' = 'abc' }", Times.Once);
restMock.Verify(Method.Post, "/user", body: "{ 'userId' = 'xyz' }", Times.Once);

// teardown
serviceMock.Teardown();
// arrange
int getUserCallCount = 0;
string encryptedConnectionString = "...";
ServiceMock serviceMock = new ServiceMock();
serviceMock.InstallCerts(certFile);
RestMock restMock = serviceMock.CreateRestMock("/api/v1", 9001, useSSL: true);
restMock.Setup(Method.Post, "/user", body: "{ 'userId' = '' }")
        .ReturnsError(400);
restMock.Setup(Method.Post, "/user", body: "{ 'userDirectory' = '' }")
        .ReturnsError(400, body: "User directory missing, what were you thinking?");
restMock.Setup(Method.Get, "/user/{id}", Parameter.Is("id", "698fa58a-8e9c-4607-b6c3-b5da19751a04"))
        .Returns(new User() { ID = new Guid("698fa58a-8e9c-4607-b6c3-b5da19751a04"), UserId = "abc" });
restMock.Setup(Method.Get, "/user")
        .Callback(() => { getUserCallCount++; });
restMock.Setup(Method.Get, "/user/detail?filter={filter}&orderby={orderby}",
               Parameter.Is("filter", "userDirectory eq 'acme'", CompareCase.Insensitive),
               Parameter.EndsWithWord("orderby", "desc", CompareCase.Insensitive))
        .Returns(new[]
  {
     new User() { ID = new Guid("607a755d-3ded-4a42-9a96-03d9ecfd31da"), UserId = "xyz", UserDirectory = "ACME" },
     new User() { ID = new Guid("698fa58a-8e9c-4607-b6c3-b5da19751a04"), UserId = "abc", UserDirectory = "ACME" }
  });
restMock.Setup(Method.Get, "/product?filter={filter}&orderby={orderby}",
               Parameter.Is("filter", filter => filter.Split(' ').Any(word => word.ToLower() == "and")),
               Parameter.IsAny("orderby"))
        .ReturnsError(500);
restMock.Setup(Method.Get, "/secure/item",
               Header.Is("X-Acme-User", "UserDirectory=INTERNAL; UserId=sa", CompareCase.Insensitive))
        .Returns(new[] { new DataConnection() { Connectionstring = Decrypt(encryptedConnectionString) } },
                 Header.Attach("Cache-Control", "private"));
restMock.Setup(Method.Get, "/secure/item",
               Header.IsNot("X-Acme-User", "UserDirectory=INTERNAL; UserId=sa", CompareCase.Insensitive),
               Header.IsNotSet("X-Acme-Security"))
        .Returns(new[] { new DataConnection() { Connectionstring = encryptedConnectionString } });
serviceMock.Activate();

// act
...

// assert
Assert.AreEqual(5, getUserCallCount);
restMock.Verify(Method.Get, "/user/detail?filter={filter}&orderby={orderby}", Times.Never,
                Parameter.IsAny("filter"),
                Parameter.ContainsWord("orderby", "userDirectory", CompareCase.Insensitive));

// teardown
serviceMock.Teardown();