I am a new guy in this Moq community.
I am wondering is there any way to put an Inheritance object of A (Mock) to a list of Mock interface A?
For example, assume we have
Class ClientA :IMyClient{...} //has override virtual codes
Class ClientB :IMyClient{...}
and
List<Mock<IMyClient>> mockClients = new List<Mock<IMyClient>>();
Is there anyway that I can do something like this:
var mockClientA = new Mock<ClientA>();
mockClients.Add(mockClientA);
I might not be on the right track. Need some help. Thanks.
=================================
Setup
// setup everyone to Free
actualManager.Status = Status.Free;
foreach (var mock in mockClients) {
mock.Object.Status = Status.Free;
actualManager.AddClient(mock.Object);
}
Test
Assert.AreEqual(Status.Free, actualManager.Status); // pass
var firstClient = mockClients.First();
IMyClient actualFirstClient = SetClientToTriggerOutsideCallbacks(firstClient);
firstClient.Status = Status.Busy;
// busy, since the first client is busy now.
Assert.AreEqual(Status.Busy, actualManager.Status); //pass
SessionSwitchEventArgs e = new SessionSwitchEventArgs(SessionSwitchReason.SessionLock);
actualManager.SystemEvents_SessionSwitch(null, e);
Assert.AreEqual(Status.Away, actualManager.Status); //not pass
I was trying to check influence of status changes on different clients, so I was trying to use a list to store all the clients.
The problem is: actualManager.SystemEvents_SessionSwitch(null, e); doesn't work correctly if the first client is not in type of ClientA.
First of all - why do we need mocks and stubs? Because our SUT (System Under Test, the object which you are testing) often has some dependencies. We cannot use real dependencies which we have in production code, because we will not be able to tell the reason why test is passing or failing. It might be error in SUT or in dependency. So we should provide something instead of real dependency which will be reliable. I.e. it should not produce any unexpected errors no matter how you change implementation of real dependencies. That's why we use stubs and mocks.
But what's the difference between them? Stubs are used in tests which do state verification. I.e. when you after exercising SUT verify state of SUT and (sometime) stub. Stub can be very simple. You can just implement dependency interface and use auto-properties without any logic inside. It's enough for you to setup some value, SUT will read/write something into stub. At the end you will check state. You will not check what operations were performed.
Behavior verification is very different. It focuses on interaction between SUT and dependencies. We setup some expectations for mock object. It's not same as setting up some properties with fake data. With mock you setup the fact that property or method should be called, and correct parameters should be passed. With stub you don't check whether it was called. You just make call possible and check state at the end.
So.. what you are doing here is state verification with mocks. Which is not how mocks supposed to be used. I.e. you setup status of clients and then check state of manager. Instead of using Moq following simple implementation completely satisfies your needs:
public class ClientStub : IMyClient
{
public Status Status { get; set; }
// some other members here
}
You can set status. Manager can read it. You can check manager's state. If you are going to use mocks, you should use behavior verification (otherwise it's just overkill). It's hard to tell what is the purpose of your manager class and how it checks status of clients. If you'll add this information I'll add some behavior verification test for your manager.
And regarding your question about putting mocks of different types into list - you cannot do that (well, only if you have list of objects). And it makes no sense. If some SUT expects list of dependencies, then you should put mock objects (accessible via Object property of mock) into that list. That's the difference between Moq and RhinoMocks.
Thank you, #SergeyBerezovskiy. I was not even in a right direction. Thank you for the ref link.
I rewrote the example of the link in C# version and tested. I think it help me understand Mock a lot. Please let me know if I made anything bad in here. Thanks.
WareHouse.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test {
public class WareHouse {
private Dictionary<string, int> wareHouseRepo = new Dictionary<string, int>();
public void Add(string location, int number) {
//null add
if (wareHouseRepo.ContainsKey(location)) {
int inventory_Old = wareHouseRepo[location];
wareHouseRepo[location] = inventory_Old + number;
} else {
wareHouseRepo.Add(location, number);
}
}
public virtual bool FillIt(string location, int number) {
if (wareHouseRepo.ContainsKey(location)) {
int inventory = wareHouseRepo[location];
if(inventory >= number){
wareHouseRepo[location] = inventory - number;
return true;
}else{
return false;
}
} else {
return false;
}
}
}
public int GetInventory(string location) {
if (wareHouseRepo.ContainsKey(location)) {
return wareHouseRepo[location];
} else {
return 0;
}
}
}
Order.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test {
class Order {
private string location = "";
private int orderNum = 0;
private bool filled = true;
public Order(string loc, int num) {
this.location = loc;
this.orderNum = num;
}
public void Fill(WareHouse wh){
if (wh.FillIt(location, orderNum)) {
filled = true;
} else {
filled = false;
}
}
public bool isFilled() {
return filled;
}
}
}
TestWareHouse.cs
using Moq;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Test {
[TestFixture]
class TestWareHouse {
private WareHouse warehouse = new WareHouse();
private static String TALISKER = "Talisker";
private static String HIGHLAND_PARK = "Highland Park";
[SetUp]
public void SetUp() {
//reset
warehouse = new WareHouse();
warehouse.Add(TALISKER, 50);
warehouse.Add(HIGHLAND_PARK, 25);
}
//regular testing
[Test]
public void testOrderIsFilledIfEnoughInWarehouse() {
Order order = new Order(TALISKER, 50);
order.Fill(warehouse);
Assert.True(order.isFilled());
Assert.AreEqual(0, warehouse.GetInventory(TALISKER));
}
[Test]
public void testOrderDoesNotRemoveIfNotEnough() {
Order order = new Order(TALISKER, 51);
order.Fill(warehouse);
Assert.False(order.isFilled());
Assert.AreEqual(50, warehouse.GetInventory(TALISKER));
}
//Now I am trying to do the things with Mock
[Test]
public void testOrderIsFilledIfEnoughInWarehouseMock() {
Order order = new Order(TALISKER, 50);
//-- Creating a fake ICustomerRepository object
var warehouseMock = new Mock<WareHouse>();
//warehouseMock
warehouseMock
.Setup(m => m.FillIt(TALISKER, 50))
.Returns(true);
order.Fill(warehouseMock.Object);
//-- Assert ----------------------
Assert.IsTrue(order.isFilled());
warehouseMock.Verify(x => x.FillIt(It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(1));
}
[Test]
public void testFillingDoesNotRemoveIfNotEnoughInStock() {
Order order = new Order(TALISKER, 51);
//-- Creating a fake ICustomerRepository object
var warehouseMock = new Mock<WareHouse>();
warehouseMock
.Setup(m => m.FillIt(It.IsAny<string>(), It.IsAny<int>()))
.Returns(false);
order.Fill(warehouseMock.Object);
//-- Assert ----------------------
Assert.IsFalse(order.isFilled());
warehouseMock.Verify(x => x.FillIt(It.IsAny<string>(), It.IsAny<int>()), Times.Exactly(1));
}
}
}
Related
I am not sure about how such a pattern named or even if it exists, but I named it 'container pattern'.
What I am trying to accomplish: to have an abstraction to hold a list of entities, being able only to add entities, and remove them only when entities saved to the database. I must say it works quite well and I like it much more than passing around List<> like I did earlier.
I just learned that testing private fields is big no-no, but I don't know how I can test Add method alone. Or how to test SaveAndClean without invoking Add. So far testing private field using additional constructor seem clean, but probably there are better solutions.
namespace test
{
class Container
{
private readonly List<Entity> _results;
private readonly IRepostory _repo;
// used for prod
public Container(IRepostory repo)
: this(new List<Entity>(500000), repo)
{
}
// used for tests
internal Container(List<Entity> results, IRepostory repo)
{
_results = results;
_repo = repo;
}
public void Add(Entity entity)
{
_results.Add(entity);
}
public async Task<bool> SaveAndClearAsync()
{
if (!_results.Any())
{
return true;
}
try
{
await _repo.SaveAsync(_results);
_results.Clear();
return true;
}
catch (Exception ex)
{
// logging
}
return false;
}
}
}
[Fact]
public void Add_AddToExisting_EntityAdded()
{
// Arrange
var results = new List<Entity>();
results.Add(new Entity { Name = "md51" });
var repo = new Mock<IRepository>(MockBehavior.Strict);
var service = new Container(results, repo.Object);
var newEntity = new Entity { Name "md52" };
// Act
service.Add(newEntity);
// Assert
Assert.Equal("md51", results[0].Name);
Assert.Equal("md52", results[1].Name);
Assert.Equal(2, results.Count);
}
In your case I would test the behavior as a black box. And from a black box perspective only calling Add doesn't produce any behavior so I'd leave it at that. But calling Add() 2 times and SaveAndClearAsync does, so just test that.
You shouldn't change your code interface for the sole purpose of testing. That's an anti-pattern as well.
I recommend this Dave Farley video on test mistakes.
I have a method CreateAccount to test. I am using Moq for the same.
Under CreateAccount method, there are multiple table insertion methods which belongs to two classes AccountRepository and BillingRepository
I have setup the Moq but don't know how to use multiple moq objects.
Below is some code snippet
Mock<AccountRepository> moq = new Mock<AccountRepository>();
Mock<BillingRepository> moqBill = new Mock<BillingRepository>();
moq.Setup(x => x.AddTable_1(new AddTable_1 { }));
moq.Setup(x => x.AddTable_2(new AddTable_2 { }));
moqBill.Setup(x => x.Table_3());
CreateAccount method takes four parameters and its under ApplicationService class
public class ApplicationService
{
public CreateAccountServiceResponse CreateAccount(AuthenticateApp App, CustomerInfo Customer, ServiceInfo Service, Optional op)
{
// SOME VALIDATION CODE
//.....................
// SOME CODE TO SAVE DATA INTO TABLES
obj_1.AddTable_1(objdata_1);
obj_1.AddTable_2(objdata_2);
obj_2.AddTable_3(objdata_3);
}
}
Please suggest some solution. How can these three methods will be skipped ?
Thanks in advance.
You have to provide some means to inject obj_1 and obj_2, since they seem to represent your instances of AccountRepository and BillingRepository, resp.
Typically, you might want to do this by using constructor injection. Extending the snippet you provided, this might look like this:
public class ApplicationService
{
private readonly AccountRepository _accountRepository;
private readonly BillingRepository _billingRepository;
public ApplicationService(AccountRepository accountRepository, BillingRepository billingRepository)
{
_accountRepository = accountRepository;
_billingRepository = billingRepository;
}
public CreateAccountServiceResponse CreateAccount(AuthenticateApp App, CustomerInfo Customer, ServiceInfo Service, Optional op)
{
// SOME VALIDATION CODE
//.....................
// SOME CODE TO SAVE DATA INTO TABLES
_accountRepository.AddTable_1(objdata_1);
_accountRepository.AddTable_2(objdata_2);
_billingRepository.AddTable_3(objdata_3);
}
}
Now you can inject your mocks into the class under test:
public void CreateAccount_WhenCalledLikeThis_DoesSomeCoolStuff()
{
var accountRepoMock = new Mock<AccountRepository>();
// set it up
var billingRepository = new Mock<BillingRepository>();
// set it up
var appService = new ApplicationService(accountRepoMock.Object, billingRepoMock.Objcet);
// More setup
// Act
var response = appService.CreateAccount(...);
// Assert on response and/or verify mocks
}
I'm trying to figure out how to do my first Mock with Moq. I'm new to mocking as well.
Lets say I have the following TDD test:
[TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
// Arrange
var preAuthorizeRequest = new PreAuthorizeRequest();
// Act
var authorizeResponse = _dataProcessor.SendRequest(preAuthorizeRequest);
// Assert
Assert.IsNotNull(authorizeResponse);
}
The scenario for that test above is that if we send in an object instance that has no state, we should still get back a response object (it shouldn't blow up). So I guess in Mock and Stub terms I guess I want to test the behavior of the dataProcessor's SendRequest method in that it'll send back an instance of PreAuthorizeResponse....right?
Now here's the info on what these types are:
public interface IPaymentRequest
{
string SecurityToken { get; set; }
int RetailID { get; set; }
int ProcessorId { get; set; }
}
public class PreAuthorizeRequest : IPaymentRequest
{
public string SecurityToken { get; set; }
public int RetailID { get; set; }
public int ProcessorId { get; set; }
public PreAuthorizeTransaction Transaction { get; set; }
}
public IPaymentResponse SendRequest(IPaymentRequest request)
{
ITransaction transaction = PaymentUtilities.GetPaymentRequestTransactionType(request);
IPaymentResponse response = PaymentUtilities.GetPaymentResponseType(request);
var transactionType = PaymentUtilities.GetPaymentRequestTransactionTypeEnum(request);
var requestValidator = new PaymentRequestValidator();
requestValidator.ValidateRequest(request);
var requestIsValid = requestValidator.RequestIsValid;
if (!requestIsValid)
{
response = PaymentUtilities.BuildPaymentResponse(request, requestValidator, transaction, transactionType);
return response;
}
IAutoPaymentProcessor autoPaymentProcessor = CreateAutoPaymentProcessor(request);
var configValidator = new ConfigurationValidator(autoPaymentProcessor);
configValidator.ValidateConfigurationSettings();
bool settingsAreValid = configValidator.ConfigIsValid;
if (!settingsAreValid)
{
response = PaymentUtilities.BuildPaymentResponse(request, requestValidator, transaction, transactionType);
return response;
}
response = SetConfigSettings(request, response);
Document dataResponseDoc = SendRequest(request, response);
response.PaymentProcessorId = (int)Enums.PaymentProcessorType.Data;
response.ProviderAuthCode = dataResponseDoc != null ? dataResponseDoc.get("Response.authcode") : string.Empty;
response.ProviderReference = dataResponseDoc != null ? dataResponseDoc.get("Response.data_reference") : string.Empty;
return response;
}
So I don't see the need for a mock, in other words a verify call on the mock right? I think I just need a stub and to test whether I get an instance of PreAuthorizeResponse back. So I guess that's a stub with Moq right?
Well then how would I do this with Moq if I'm right about me only needing to work with a stub here?
I tried this but I feel this is wrong since I feel the SUT is my data processor which I believe you should not mock the object in test:
[TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
// Arrange - setup data
var dataProcessorStub = new Mock<IPaymentProcessor>();
var preAuthorizeRequest = new PreAuthorizeRequest();
// Act
//setup - expectations
dataProcessorStub.Setup(p => p.SendRequest(It.IsAny<PreAuthorizeRequest>())).Returns(It.IsAny<PreAuthorizeResponse>());
// excercise
var preAuthorizeResponse = dataProcessorStub.Object.SendRequest(preAuthorizeRequest);
// Assert
Assert.IsInstanceOfType(preAuthorizeResponse, typeof(PreAuthorizeResponse));
}
No, you don't really want to be mocking the object you are trying to test. You should mock the dependencies of that object (e.g. the database object).
The dataProcessor is the Object under Test (also known as System under Test), and everything else are collaborators (dependencies of the SUT).
You are going to find it difficult to test this properly though, due to the number of hard dependencies that you have within the SendRequest method.
At the very least, you want to mock the PaymentRequestValidator so that when you send in a specific type of request, you can have the mock setup to say that it is not valid, and then handle that in the code, which in turn will cause the SendRequest method to return a response.
To achieve that though, you will need to refactor your code in order to pass a mocked instance of the request validator in. Also, probably quite a few of the other objects as well.
For example, you'll more than likely need to mock the PaymentUtilities object so that you can have the methods you use return Mock objects, which are themselves setup to return specific things for this test. Similarly the ConfigurationValidator - will it return a valid configuration when it is called from the test (probably a different test), or do you need to mock that as well?
This is heading well into the realms of dependency injection and inversion of control. I won't insult you are by providing links, but those subjects are well covered in literature both in print and on the web.
Looking at the code, it seems like you don't need to do any mocking if you are trying to test the SendRequest method. You need to mock the dependencies of what you are trying to test, not the object under test itself. So if your PaymentProcessor had any external dependencies required for the test you'd need to mock those.
The SendRequest method does take an interface which you can mock, but it's easier to just pass in a newly created PreAuthorizeRequest.
[TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
// Arrange
var preAuthorizeRequest = new PreAuthorizeRequest();
// Act
var authorizeResponse = _dataProcessor.SendRequest(preAuthorizeRequest);
// Assert
Assert.IsNotNull(authorizeResponse);
}
Alternatively you can mock the request:
[TestMethod]
public void PreAuthorize_WithEmptyRequest_ReturnsNonNullResponse()
{
// Arrange
var request = new Mock<IPaymentRequest>();
// Act
var authorizeResponse = _dataProcessor.SendRequest(request);
// Assert
Assert.IsNotNull(authorizeResponse);
}
I'm practicing on writing unit tests for the first time, and I have some questions. I'll start of by explaining what I'm trying to test.
I would like to test a method which looks like this:
public bool IsAdmin(HubCallerContext hubCallerContext)
{
return hubCallerContext.User.IsInRole("admin");
}
The method is implemented in a class UserService, which is connected to a interface IUserService.
I'm trying to create 2 tests:
One with a HubCallerContext which is in the role of "admin" and will assert true.
One with a HubCallerContext which is in the role of "user" and will assert false.
I've created a new class library in my solution, where I've refrenced the project I'm testing. I've installed NUnit and Moq, and created a test class which looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChatProj;
using NUnit.Framework;
using ChatProj.Controllers;
using Moq;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ChatProj.DAL;
using ChatProj.Service_Layer;
using System.Threading.Tasks;
namespace ChatProj.Tests
{
[TestFixture]
public class Class1
{
[SetUp]
public void Setup()
{
}
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
bool result = userService.IsAdmin( ? );
Assert.IsFalse( result, "Something is wrong." );
}
}
}
Here I start to get confused. (I've marked the parameters of the IsAdmin calls with "?" because I'm not sure what to put there.)
I've read about mocks, stubs, fakes and dummies, but the definitions are to abstract for me to really grasp. I've found these definitions for example:
- Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
- Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
- Mocks are objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
As I've designed my test class, I would need some sort of substitution for my HubCallerContext. This is assuming I'm testing the "IsAdmin" method the right way.
So my questions are:
Am I testing the "IsAdmin" method in a good way?
How would I practically make the tests work? Do I use a mock, and in that case, could you show how I would implement that, or point me in the right direction? Here is how the HubCallerContext works for
refrence.
Assuming HubCallerContext is this one - https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/Hubs/HubCallerContext.cs - then setting up the tests will be easy. You just want two mocks of IPrincipal, one of which returns true for the .IsInRole("admin") call and the other that returns false.wrap these two in mocks of IRequest.
The syntax will vary depending on the mocking framework used, but your tests will end up something like:
[Test]
public void IsAdmin_CalledByAdmin_ReturnTrue()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsTrue( result, "Something is wrong." );
}
[Test]
public void IsAdmin_CalledByUser_ReturnFalse()
{
UserService userService = new UserService();
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
var requestMock = new Mock<IRequest>();
requestMock.Setup(x => x.User).Returns(principalMock.Object);
var result = userService.IsAdmin(new HubCallerContext(requestMock.Object, ""));
Assert.IsFalse( result, "Something is wrong." );
}
I haven't checked if the above compiles, but it is based on the syntax needed for Moq.
I think that it would be much easier for You to write these two unit tests if You would change the method under test a little (assuming it's not a part of legacy code).
If you define the method this way:
public bool IsAdmin(IPrincipal user)
{
return user.IsInRole("admin");
}
things would get pretty simple (btw. check the "Law of Demeter" ;)). You can pass in a mock object (since the user parameter is an interface - IPrincipal) returning true if the user should be in role "admin" and false otherwise.
The benefit of this solution is that You don't have to build a graph of mock objects and the arrange part of your test is pretty simple. Your tests could look somewhat like this:
[Test]
public void IsAdmin_CalledByAdminUser_ReturnTrue()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(true);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsTrue(result);
}
[Test]
public void IsAdmin_CalledByNonAdminUser_ReturnFalse()
{
//Arrange
var principalMock = new Mock<IPrincipal>();
principalMock.Setup(x => x.IsInRole("admin")).Returns(false);
//Act
var userService = ...// create an instance of userService here
var result = userService.IsAdmin(principalMock);
//Assert
Assert.IsFalse(result);
}
I would recommend You to read this series of blog posts (I think it's pretty cool :)): http://www.daedtech.com/tag/unit-testing
You can get the list of roles and check for each roles using foreach.
I get very confused when I have to unit test a method which is calling multiple public methods of other classes. Here is the example
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SkillKindle.BLL;
using SkillKindle.BLL.ClassDetails;
using SkillKindle.BLL.SkClasses;
using SkillKindle.Domain.Models.SkClasses;
using SkillKindle.Infrastructure;
using SkillKindle.Web.Core.Infrastructure.ErrorHandling;
using SkillKindleWeb.Mappers;
using SkillKindleWeb.ViewModels.ClassDetails;
namespace SkillKindleWeb.Controllers
{
[CustomHandleError(ExceptionType = typeof (BusinessValidationException))]
public class ClassDetailsController : BaseController
{
private readonly ILogger _logger;
private readonly IMapperService _mapperService;
private readonly IAccessorFactory _accessorFactory;
private const int RegistrationId = 34;
private IClassDetailsAccessor ClassDetailsAccessor
{
get { return _accessorFactory.CreateClassDetailsAccessor(); }
}
private ISkClassAccessor SkClassAccessor
{
get { return _accessorFactory.CreateSkClassAccessor(); }
}
private IClassCreativeAccessor ClassCreativeAccessor
{
get { return _accessorFactory.CreateClassCreativeAccessor(); }
}
public ClassDetailsController(ILogger logger, IMapperService mapperService,
IAccessorFactory accessorFactory)
{
_logger = logger;
_mapperService = mapperService;
_accessorFactory = accessorFactory;
}
public ViewResult Index(int classCreativeId)
{
var classCreative = ClassCreativeAccessor.GetClassCreative(classCreativeId);
if (classCreative == null)
{
throw new HttpException(404, "The url is not valid");
}
var batches = ClassCreativeAccessor.GetFutureBatches(classCreativeId);
IList<ClassTicket> tickets = new List<ClassTicket>();
IList<Venue> venues = new List<Venue>();
if (batches.Count > 0)
{
tickets =
ClassCreativeAccessor.GetTickets(
batches.Select(batch => batch.ClassScheduleId).Distinct().ToArray());
venues = SkClassAccessor.GetVenues(batches.Select(batch => batch.VenueId).Distinct().ToArray());
}
var classDetailsViewModel = _mapperService.ClassCreativeToClassDetailsViewModel(classCreative);
var batchViewModels = _mapperService.BatchToClassDetailsBatchViewModel(batches).ToList();
var ticketViewModels = _mapperService.ClassTicketToClassDetailsTicketViewModel(tickets).ToList();
var venueViewModels = _mapperService.VenueToClassDetailsVenueViewModel(venues).ToList();
var indexViewModel = new IndexViewModel()
{
Batches = batchViewModels,
Tickets = ticketViewModels,
ClassDetails = classDetailsViewModel,
Venues = venueViewModels
};
return View(indexViewModel);
}
}
}
Here Index method is dependent on mapperService, SkClassAccessor, ClassDetailsAccessor,
ClassCreativeAccessor public methods. I have unit tested those public method separately. Now when it comes to test Index method, I need to check the correctness of indexViewModel. Here are couple of options with me.
Option 1. Mock the public methods of dependent classes to return fake objects and check IndexViewModel has those fake object. I am not sure if this is a real test. Also it does not test that I am passing the write arguments to these mock public methods.
Option 2. Don't mock the public methods of dependent classes but fake the dependencies of dependent classes. e.g. Fake the list of tickets ClassCreativeAccessor.GetTickets would operate on. This approach would verify that I passing the right argument to dependent public methods. But here I would be testing public methods again
I am not sure which approach is correct. Appreciate you help.
I am not sure if this is a real test.
This is a unit test as it should be. Don't mix it up with integration test.
Also it does not test that I am passing the write arguments to these
mock public methods.
When you are mocking dependencies (first option) you always can verify that methods was called with appropriate parameters. E.g. with Moq:
mock.Verify(foo => foo.Execute("ping"));
will check if method Execute of dependency foo was called with parameter "ping". Same way you can verify your ClassCreativeAccessor was called with appropriate parameters:
int classCreativeId = 42;
List<Batch> batches = new List<Batch>();
creativeAccessorMock.Setup(ca => ca.GetFutureBatches(classCreativeId))
.Returns(batches);
...