I am attempting to setup a simple unit test for my code. I have an interface and implementation that talks to an external service via WCF. I am attempting to mock this with the code below;
private Mock<IPayments> _mockIPayments;
_mockIPayments.Setup(x => x.GetCreditCard(It.IsAny<GetCreditCardRequest>())).Returns(getCreditCardResponse);
In the unit test itself, I create an instance of the service that would ultimately call the WCF service;
var paymentService = new PaymentService();
var response = paymentService.GetCardDetails(cardId);
Within the PaymentService itself, the code;
var response = ServiceInvoker.Invoke<IPayments, GetCreditCardRequest, GetCreditCardResponse>
(
"Payments",
request,
(proxy, req) => proxy.GetCreditCard(req));
(Note that ServiceInvoker.Invoke is just a wrapper to create a channel and process the request)
Am I missing something, should the mock setup not be catching the request to GetCreditCard?
ETA
To make it a little clearer, the flow is;
UnitTest -> PaymentsService -> IPayments
You need to pass your mocked instance to the service somehow.
var paymentService = new PaymentService(_mockIPayments.Object);
Simply specifying a setup will not let Moq replace all instances of some interface with the what you specified. It simply defines what Moq will return when a certain Mock instance will be called. In your case _mockIPayments.
You then have to use that mocked IPayments instance in your code (either pass it in a constructor or method) for your code to actually use it.
If your PaymentService is currently creating an IPayments object internally, to use mocking you will have to use something like Dependency Injection so that you are able to specify the IPayments instance externally and thus supply a mock instance in your tests.
Likewise:
var paymentService = new PaymentService(_mockIPayments.Object);
Related
I use AutoFac. I have to resolve a type with an explicit instance which I get from another service.
For example: I have an instance of type Client which I get from somewhere (not from the container).
I want to configure the Autofac container so that always when an object of type Client should be resolved, it should return my instance.
Problem is that I don't have this instance at the time, when I configure the container with the Containerbuilder - so I cannot use for example LambdaRegistration.
Is there another solution for solving my problem?
You can do the following:
MyService service = null;
builder.Register(c => service).As<IMyService>();
// Later on
service = new MyService();
Depending on your needs there are quite some variations of this approach possible, such as:
Send a 'setter' delegate to some initialization code that will call the delegate after the service gets created, e.g. MyServiceInitializer.AfterInitialization(s => service = s);
Promote the service variable to a class property and provide that new wrapper to the initialization
Hide access to the service behind specific read and write abstractions, e.g. interface IMyServiceContext { IMyService Current { get; } } and interface IMyServiceSetter { void SetCurrent(IMyService service); }.
Prevent Autofac from accidentally resolving the service before it is initialized by throwing an exception instead of throwing null, e.g. Register(c => service ?? throw new InvalidOperationException("..."))
It's important to note, however, that in general, the creation of components should be fast and reliable. The fact that your component isn't available at startup is likely because it requires I/O to setup. This is a situation should should try to prevent, for instance by hiding it behind an abstraction completely. This allows you to implement a Proxy that allows the real service to be lazy loaded.
Hopefully this gives you some clues on how to solve this.
I am having an issue while testing one of the service method which uses an async Repository method.
Repository layer
public interface IRepo
{
Task<Model> GetByIdAsync(string Id);
Task SaveAsync(Model model);
}
Service layer
void Process(string Id)
{
var model = _repo.GetByIdAsync(Id).Result;
model.Field1 = "update";
_repo.SaveAsync(model).Wait();
}
Unit test against service layer
[Fact]
SUTServiceTest()
{
//Arrange
Model model = new Model();
var mockRepo = Mock.Get(new Repo());
mockRepo.Setup(x => x.GetByIdAsync(It.IsNotNull<string>()))
.Returns(() => Task.FromResult(model));
mockRepo.Setup(x => x.SaveAsync(It.IsAny<Model>()))
.Callback<Model>((obj) => model = obj);
var _service = new SUTService(mockRepo);
//Act
_service.Process("1");
//Assert
Assert.Equal("update", model.Field1);
}
I'm getting the following error at _repo.SaveAsync(model).await();:
System.NullReferenceException - Object reference not set to an instance of an object
Not sure what did I miss.
The intent behind this answer is to capture valuable information from the chat discussion.
As the OP said a NullReferenceException has been thrown at the following line:
_repo.SaveAsync(model).Wait();
The _repo tried to be initialized in the following way in the unit test:
var mockRepo = Mock.Get(new Repo());
That's not the correct way to do it. Please check the documentation of the Mock.Get to know when it should be used and for what purpose.
The _repo should be initialized in the following way:
var mockRepo = new Mock<IRepo>();
The OP had the following observation after changing the mock creation:
However, I loose the DI setup that I have for Repo construction
In short: That's the whole point.
Whenever you are unit testing a component then you try to mock out (simplify and mimic) all of its dependencies. It needs to rely on stubs and spies to be able to verify which one of them have been called under certain circumstances but the concrete implementation of the mocked objects do not matter.
In this particular case that means that the Service layer do not want to rely on a concrete Repository instance. It needs only a repo, which can capture the calling parameters and which can verify its calling.
FYI: Testing terminologies
Dummy: simple code that returns bogus data
Fake: a working alternative which can take shortcuts
Stub: custom logic with predefined data
Mock: custom logic with expectations (interactive stub)
Shim: custom logic at run-time
Spy: interceptors to record calls
Ive written a couple of unit tests while using dependency injection and the httpClient in the .net Core 2.0 framework.
Ive been testing my controllers like this:
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
But now i wanted to mock an object and after searching a bit on the internet all i could find was to do it like this:
var controller = new ProductionLineController(mockProductionLineProvider);
which is not testing the routing and on top of that i would have to create a lot of objects. so i dont want mock my object in this way.
I would like to be able to replace the service with an mock object i havent found a way to get the IServiceCollection into my unittest method.
I would like to be able to do something like this:
var mockingDate = new DateTime(date.Year, date.Month, date.Day, 12, 00, 00);
__constantsMock.Setup(x => x.GetCurrentDateTime()).Returns(mockingDate);
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
var result = await __client.PostAsync("api/production-line/validate-assignment-deadline", null);
I hope you can help me think of ways to get to a solution that doesnt involve me having to create every object that i would inject normaly.
Thank you in advance
edit:
im indeed doing integration tests, i want to test everything but i need to be able to configure the result coming from a DateTime.Now so i made the constants class with a function to return the datetime.now and im trying to mock/stub the class/function. that way i can test multiple scenario's that could occur.
You are looking at the standard way of mocking; you create stubs for all the dependencies (you need to be able to control all of them!) and create the controller. Being able to mock the DI framework wouldn't really buy you anything; you would still need to provide all the dependencies to the class when you constructed it.
Use mocking libraries like NSubstitute to make it easier; if you feel like you have too many dependencies then I would suspect you need to refactor your design (perhaps that controller does too much).
Note that testing with actual HTTP requests is more of an integration test; you are testing the whole app instead of just one class. In that case you can set up different environments for your program and have one that will set up the injector with whatever extra mocks/test data you need.
Once you start doing something like issuing a request to an action, you're pretty much well outside of unit test territory. What you're doing here is integration testing.
As long as you're doing integration testing, you might as well use TestServer, which will actually give you a much more accurate platform for integration tests. Setting up all the dependencies manually doesn't do anything for you in ensuring that your application actually functions as it should. The full documentation is here, but basically, you just do:
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_client = _server.CreateClient();
The return of _server.CreateClient() is actually an instance of HttpClient, so your actual test code doesn't really need to change. However, now you've got a full mockup of all your services and config baked in.
The solution to my problem was as follows:
Make an extra starting class that inherits from your StartUp class
Give that class the following code:
public class UnitTestStartup : Startup
{
public static IServiceProvider ServiceProvider;
public static IServiceCollection Services;
public static Mock<IConstants> ConstantsMock;
public void ConfigureTestingServices(IServiceCollection services)
{
ServiceProvider = base.ConfigureServices(services);
Services = services;
ConstantsMock = new Mock<IConstants>();
services.Replace(new ServiceDescriptor(typeof(IConstants), ConstantsMock.Object));
}
}
Make the ConstantsMock (the service you want to mock) available in your baseclass
Like this:
protected Mock<IConstants> __constantsMock;
__constantsMock = UnitTestStartup.ConstantsMock;
have every unit test class inherit from your baseclass
override the __constantsMock with a new object and you're done
I have some integration tests that run by using ChannelFactory to create an instance of the service.
My normal WCF Service is setup using Simple Injector, but I can't seem to figure out how to get that to work with my ChannelFactory code.
Here is what my test setup code looks like:
private readonly IMyService myChannel;
public TestingClient(Binding binding, string serviceUrl)
{
var endpointAddress = new EndpointAddress(serviceUrl);
var myChannelFactory = new ChannelFactory<IMySErvice>(binding, endpointAddress);
myChannel = myChannelFactory.CreateChannel();
}
When I run my tests it looks like myChannel.MyServiceOperation(); But I get an error of:
The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor
This is because normally WCF does not support constructors with parameters. But SimpleInjector fixes that and allows for parameters that it knows how to construct.
Because of this MyService has a constructor that looks like this:
public MyService(Validations validations)
{
this.validations = validations;
}
And Validations is injected by Simple Injector (see here for how that is setup without a ChannelFactory)
But since I am setting it up manually with the ChannelFactory, I don't know how to get SimpleInjector in the mix (so it can inject the Validations object).
Can anyone tell me how to get Simple Injector to work with a ChannelFactory?
I am currently writing an API wrapper in C# for ResellerClub's REST/HTTP API, which provides responses in garden-variety JSON objects. Invocation is performed by performing HTTP POST/GET on API endpoints using the HttpClient class. JSON.Net is used for parsing the responses.
How I can unit test my API wrapper functionality for the API as most calls require a level of expected state in order to succeed. For example, I cannot test the creation of a CNAME record on a domain that I have not already registered.
I understand that tests should never rely on state which they do not arrange themselves, and I've also been told that the tests should never actually deal with any kind of persistence mechanism such as a database. So, for the above example of a CNAME record, that as part of the "Arrange" phase of the test I should register a test domain, assert it worked, then do the actual CNAME function?
Alternative, should I come up with some way of mocking the JSON responses that are returned from the Reseller Club API?
EDIT: Example of my API class (ResellerClubApi.cs)
private async Task<string> DownloadString(string uri)
{
// HttpClient object downloads the JSON response string asynchronously
}
The DownloadString() method is used by my functionality as a generic means of grabbing the response from the third party service.
public async Task<List<string>> SuggestNames(string domainName)
{
// Calls DownloadString() with the correct URI, uses Newtonsoft.JSON to parse
// string representation of JSON into object
}
Methods such as SuggestNames() above are called like this from the higher service layer
public void someServiceLayerMethod()
{
var rcApi = new ResellerClubApi();
var x = rcApi.SuggestNames("something");
// ...
}
As you can see, I am a bit stuck as to how to mock JSON responses from the likes of HttpClient when my ResellerClubApi class is the lowest possible layer of my own code prior to doing things over HTTP.
I also don't know how to start using IoC to hand the HttpClient dependency...
Thanks
I would separate the code from your ResellerClubApi class which involves downloading stuff and authorization, and everything that involves connecting to a remote service, in let's say a ResellerClubClient and have it implement a IResellerClubClient interface.
public interface IResellerClubClient {
string RequestJson(string url);
}
public class ResellerClubClient : IResellerClubClient {
// implement your methods here
}
public ResellerClubApi : IResellerClubApi {
private readonly IResellerClubClient client;
// Pass the client as dependency, either manually or using Dependency framework of your choice
public ResellerClubApi(IResellerClubClient client) {
this.client = client;
}
public List<string> SuggestNames(string domainName) {
var jsonString = this.client.RequestJson("http://example.com/domains/?name="+domainName);
// decode it and do something with it
}
}
This allows you to test your ResellerClubApi class without being depending on a concrete IResellerClubClient implementation. And the best is, you can change it (from HttpClient to socket or whatever and don't ever have to touch your ResellerClubApi.
And then set up your Unit test in framework of your choice. Some example with Moq framework:
var mockedJsonString = '{ succes: true, names: ["domainA.com", "domainA.us"] }';
// create mockup object using IResellerClubClient interface
var resellerClubClient = new Mock<IResellerClubClient>();
// Tell the mock object to return "mockedJsonString" when any parameter is passed to RequestJsonString.
// If you do more than 1 call in a test, or if that's expected to be called multiple times inside
// the method to be tested, you can setup multiple conditions and results this way too
resellerClubClient.Setup(x => x.RequestJson(It.IsAny<string>())).Returns(mockedJsonString);
var api = new ResellerClubApi(resellerClubClient.Object);
List<string> names = api.SuggestNames("domain.com");
// do your assertions here
By having abstracted the connection and data retrieving methods into hit's own class represented by an interface, you made your Api class UnitTestable and easy to mock server responses.
Of course, the ResellerClubClient can't be Unit tested of course. But it can be done in an integration test or a verification test. A UnitTest should never involve connecting to a server or a database.
Here is a way to do it by mocking the HttpMessageHandler using Moq unit test. http://geekswithblogs.net/abhi/archive/2013/11/20/unit-tests-for-httpclient-using-httpmessagehandler.aspx