I'm doing an ASP.Net MVC2 project and developing some unit test cases on it. In one of my controllers,
String AllowedActions = "";
AllowedActions = entities.sp_IsAuthorized(GetLoggedUserId(), 1, item.SubCategoryId, "CreateMeeting_HTML").FirstOrDefault();
I was unable to mock this sp_IsAuthorized() method ,
public ObjectResult<global::System.String> sp_IsAuthorized(.....){
}
I tried to mock it in this way,
var entity = new Mock<TestMVCProductEntities>();
entity.Setup(x => x.sp_IsAuthorized(...)).Return(???);
but I have no clue how to return
ObjectResult
this type of object. Help me.
You can't create a new instance of ObjectResult and you can't mock it because it is marked as sealed. I would recommend you to wrap your usage of the data context into a unit of work or similar pattern, making it testable in a unit test.
Related
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 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);
I've got a controller with a lot of constructor injection:
public MoviesController(ISession session, IClientContext clientContext, PManager pManager, ISegmentationService segmentationService, IGeoLocator geoLocator, IBus bus)
{
_session = session;
_clientContext = clientContext;
_pManager = pManager;
_segmentationService = segmentationService;
_geoLocator = geoLocator;
_bus = bus;
}
From my understanding (just read about Mocking), I've got a lot of Mock object properties to manually set if I wish to make a comprehensive test suite based on this controller.
For one method I'm only using one service (I'd even like to automate that with little effort if possible):
public object Show(Guid id)
{
var movie = _session.Get<movie>(id);
return movie;
}
But in another there are many services being used - is there any way to set those Moq objects up quickly? I could really use some examples as I'm new to testing. It's an asp.net mvc project with webapi 1 bundled in (testing the webapi controller here)
As has been said in the comments, if you have common setup code, you can put it in a Setup method that is called automatically from your testing framework before each test. It's decorated with a Setup attribute if you're using Nunit TestInitialize if you're using MStest. If you're using XUnit then it's a bit different.
So, your class might look like this:
public class SomeTests {
Mock<ISession> _sessionMock;
Mock<IClientContext> _clientContextMock;
[Setup]
public void Setup() {
_sessionMock = new Mock<ISession>();
_clientContextMock = new Mock <IClientContext();
}
MovieController CreateSut() {
return new MovieController(_sessionMock.Object, _clientContextMock.Object, ...);
}
[Test]
public void TestSomething() {
_sessionMock.Setup(x=>...);
//...
var sut = CreateSut();
//...
}
}
If you're trying to get away from completely creating the mocks manually, then you might want to look at something like AutoFixture with AutoMoq. Which will automatically supply mock instances when creating objects that accept interfaces. AutoFixture can be quite useful, but there is a learning curve to using it effectively so you might want to look at a tutorial / quickstart.
You could also configure an IOC container to supply mock instances for your test project, although I've never gone down that route myself.
For your example, you only need to mock the session, and can leave all the other dependencies null, since their behaviour should be irrelevant to the behaviour you are testing:
Mock<ISession> mockSession = new Mock<ISesssion>();
MoviesController controller = new MoviesController(mockSession.Object, null,null,null,null,null);
There is no need for you to set up any mocks other than the ones you need for this particular test
I can't test any logoff, login, register action from AccountController with the new Microsoft Fake Framework without having this error message: System.Security.VerificationException: Operation could destabilize the runtime.
The unit test is real simple:
[TestMethod]
public void LogOff()
{
var AccountController = new AccountController();
RedirectToRouteResult RedirectToRouteResult;
//Scope the detours we're creating
using (ShimsContext.Create())
{
ShimWebSecurity.Logout = () => { };
var test = AccountController.LogOff();
RedirectToRouteResult = AccountController.LogOff() as RedirectToRouteResult;
}
Assert.IsNotNull(RedirectToRouteResult);
Assert.AreEqual("Index", RedirectToRouteResult.RouteValues["Action"]);
Assert.AreEqual("Home", RedirectToRouteResult.RouteValues["controller"]);
}
Also find this: http://social.msdn.microsoft.com/Forums/en-US/vsunittest/thread/f84962ea-a9b2-4e0d-873b-e3cf8cfb37e2 that talk about the same bug but no answer.
Thanks!
I asked the same question before VS2012 Update 1 was released (VerificationException when instantiating MVC controller during unit testing) and I got the response from a guy from Microsoft who said that they are working on it and it should be available in the next update. Well, nothing since then.
However, in order to get the result and to continue testing using Microsoft Fakes Framework, I wrapped the calls to MVC methods like those in the UrlHelper class with my own private methods that return primitive types like string and then Shim the unit test to give me a desired result. That way I never made a call to the underlying MVC infrastructure and I got the desired result. Also, you will need to remove System.Web.Mvc.Fakes reference otherwise VerificationException will keep popping up.
If you find this tedious then you should switch to a more mature unit testing framework like Moq or Rhino.