How to make UnitTests run twice with different mockup settings - c#

I have a project that supports multiple deployments mode: InMem, OnPremise, Cloud.
Also each projects have small services like TimeDistance which can be conected either to WCF, either to an API.
In the unitTestMockup i can say which one i want to use:
Service.TimeDistance = new WCFTimeDistance() / new APITimeDistance().
Until now i had only WCFTimeDistance but now we are in transition mode to move to APITimeDistance but in the meantime i want when i run the tests to run twice, once with WCF once with API.
What's a good approach to do this?
I use C# 4.5
Microsoft.VisualStudio.QualityTools.UnitTestFramework as framework for unitTests
A simple example of desired workflow would be this:
1)Mockup: Service.TimeDistance = new WCFTimeDistance();
2)UnitTest: CheckDistanceBetweenTwoLocationsTest()
{
Service.TimeDistance.CalculateDistance(Location1, Location2) // WCFTimeDistance
}
3)Mockup: Service.TimeDistance = new APITimeDistance();
UnitTest: CheckDistanceBetweenTwoLocationsTest()
{
4)Service.TimeDistance.CalculateDistance(Location1, Location2) // APITimeDistance
}

Create two unit tests. Also look into using abstractions instead of static classes. It would make mocking and testing easier.
This is for your current setup
[TestClass]
public class TimeDistanceTests {
//change these to the needed types
object Location1;
object Location2;
double expected;
[TestInitialize]
public void Init() {
//...setup the two locations and expectations
Location1 = //...
Location2 = //...
expected = //...the distance.
}
[TestMethod]
public void Check_Distance_Between_Two_Locations_Using_WCF() {
//Arrange
var sut = new WCFTimeDistance();
//Act
var actual = sut.CalculateDistance(Location1, Location2);
//Assert
//...some assertion proving that test passes or failed
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void Check_Distance_Between_Two_Locations_Using_API() {
//Arrange
var sut = new APITimeDistance();
//Act
var actual = sut.CalculateDistance(Location1, Location2);
//Assert
//...some assertion proving that test passes or failed
Assert.AreEqual(expected, actual);
}
}
Ideally you would want to abstract the service. Assuming something like
public interface ITimeDistance {
double CalculateDistance(Location location1, Location location2);
}
Your Service would use the abstraction instead of a concretion.
public class Service {
ITimeDistance timeDistance
public Service(ITimeDistance timeDistance) {
this.timeDistance = timeDistance;
}
public ITimeDistance TimeDistance { get { return timeDistance; } }
}
So now in your unit tests you can swap the different implementations of your time distance service.

Related

dotnet core web app unit test controller

I have a dotnetcore web app and am looking to unit test the controllers. How do I get about this?
I have a simple controller that looks like this
public class ConversionController : Controller {
private readonly INumberService _numberService;
public ConversionController(INumberService numberService)
{
this._numberService = numberService;
}
// GET http://localhost:9789/api/conversion/123
[HttpGet("{number}")]
public string Get(decimal number)
{
return _numberService.ConvertToWords(number);
}
}
The INumberService is passed in as a parameter. How do I unit test this?
By mocking the interface/dependency and exercising an isolated unit test for the Get method. You could either create your own mock or use a mocking framework to mock the dependency. From there assert that the system under test behaves as expected.
For example the following simple test uses Moq to mock the dependency and test the Get method.
[TestMethod]
public void ConversionController_Get_Should_Return_Five() {
//Arrange
var number = 5;
var expected = "five";
var mock = new Mock<INumberService>();
mock.Setup(_ => _.ConvertToWords(number)).Returns(expected);
var sut = new ConversionController(mock.Object);
//Act
var actual = sut.Get(number);
//Assert
Assert.AreEqual(expected, actual);
}
You should also take some time and check the documentation provided
Unit Testing in .NET Core

How I can test a particular method in my Service class using Mock C#?

Please help me with my issue. I have a Service class which is given below:
public class RateService:IRatesService
{
...
public RatesDTO GetById(int Id)
{
return Mapper.Map<Rates, RatesDTO>(this.db.Rates.GetAll().Where(m => m.RateId == Id).First());
}
}
An interface IRatesServicelooks like that sample of code:
public interface IRatesService
{
.....
RatesDTO GetById(int Id);
....
}
And now I try to test public RatesDTO GetById(int Id) method. My code is given below:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Mock<IRatesService> mock = new Mock<IRatesService>();
mock.Setup(m => m.GetById(It.IsAny<int>())).Returns<RatesDTO>(total=>total);
Assert.IsNotNull(mock.Object.GetById(1));
}
}
But when I run test I get an error like this:
Test Name: TestMethod1 Test
FullName: Provider.Tests.Services.UnitTest1.TestMethod1
Result Message:
Test method Provider.Tests.Services.UnitTest1.TestMethod1 threw
exception: System.ArgumentException: Невозможно преобразовать объект
типа "System.Int32" к типу "Provider.BLL.DTO.RatesDTO".
What is the best practice to test the Service classes and methods?
You are trying to test your mock. That doesn't make any sense.
You should strive to test your actual code.
In your case, you might want to make sure that your GetById returns RatesDTO with the right id value.
You could use Mock framework, to facilitate your testing.
e.g. if you are trying to perform a unit-test and you are using a DB layer you might want to mock the database layer GetAll function and return several objects and then run a test to check that you actually return the right object (same id).
Your RateService is the system under test. When creating mocks for your unit tests the norm is to mock the dependencies of your system under test.
So given your current service lets say it has a dependency on a data store.
public class RateService : IRatesService {
private readonly IDbContext db;
public RateService(IDbContext dbContext) {
this.db = dbContext;
}
//...
public RatesDTO GetById(int Id) {
return Mapper.Map<Rates, RatesDTO>(this.db.Rates.GetAll().Where(m => m.RateId == Id).First());
}
//...
}
IDbContext would be the dependency of the system under test.
You would mock that up when testing RateService
[TestClass]
public class RateServiceUnitTests {
[TestMethod]
public void Given_ValidId_GetById_Should_Return_Dto() {
//Arrange
var validId = 1;
var fakes = new List<Rates>() {
new Rates { RateId = validId }
};
var mock = new Mock<IDbContext>();
//Assuming IDbContext.Rates.GetAll() returns an IEnumerable<Rates>
mock.Setup(m => m.Rates.GetAll()).Returns(fakes);
var sut = new RateService(mock.Object);
//Act
var result = sut.GetById(validId);
//Assert
Assert.IsNotNull(result);
}
}
Noticed that you are also using a mapper. You should make sure that is configured for the test as well otherwise the test will fail. When using static calls in your classes they can cause issues when you try to isolate your system for testing. Try adding the mapper as a dependency as well.

How do I execute an automated test with the option of specifying test type

How do I execute an automated test with the option of specifying it as a unit test or "light-weight integration test" without writing the same test twice and only changing the interface it depends on to make it either of the two?
Specifically, I want to execute one test and specify it as a unit test or an integration test.
Based on the mode I select, the test should generate a service interface.
I do not want to maintain two sets of identical code with the only difference being an interface:
Service for accessing external system (integration test)
MockService (unit test)
Example:
Construct testable business layer logic
It doesn't make sense to have a morphic test.
A unit test tests that a single piece of code works in isolation.
An integration tests tests that your code works when integrated into a larger codebase.
For instance, acceptance criteria and psuedocode for unit testing a viewmodel:
public TestMeViewModelTests {
public when_adding_a_warehouse_then_should_call_service_AddNewWarehouse_given_WarehouseModel {
//Arrange
var warehouseViewModel = new WarehouseViewModel { id=1 };
var service = new Mock<IService>();
var interfaceViewModel = new TestMeViewModel(service.Object);
//Act
interfaceViewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(wareHouseViewModel), Times.Once);
}
}
See, there's no cross-pollination of concerns. You're just testing that an idempotent operation is called when adding a new warehouse. If you were using an ORM, then you'd also have unit tests verifying that the dataservice calls are occurring.
If you were going to do an integration test, then your test project would be pointed to a "WarehouseTest" connectionstring that mirrors production, and your integration test might do that same logic, but then check to make sure that the warehouse that is inserted by the test is actually in your DB at the end of the test.
Okay, I think I understand what's happening now.
You want to be able to change the implementation used of an interface at runtime in order to change the location the unit tests run against.
In that case, you want some kind of abstract factory pattern.
Example:
public class ViewModel {
IService _service;
public ViewModel(IServiceFactory factory){
_service = factory.Create();
}
public void SaveWarehouse(Warehouse aWarehouse) {
_service.AddWarehouse(aWarehouse);
}
}
public interface IServiceFactory {
IService Create();
}
public class ProductionFactory : IServiceFactory { //Dependency injected
public IService Create() {
return new ProdService();
}
}
Unit Test:
public class ViewModelTest {
public void when_adding_warehouse() {
//Arrange
var aWarehouse = new WarehouseViewModel { id=1 };
var serviceFactory = new Mock<IServiceFactory>().Object);
var service = new Mock<IService>();
serviceFactory.Setup(factory => factory.Create()).Returns(service.Object);
var viewModel = new ViewModel(serviceFactory.Object);
//Act
viewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(aWarehouse), Times.Once);
}
}
Integration Test:
Your integration test will include a local internal IService implementation and a local internal IServiceFactory implementation returning the local IService implementation. All of your tests will run perfectly fine and you can control where the data goes to very easily.
Add an entry to the app config.
App Config:
<appSettings>
<add key="IsUnitTest" value="True" />
</appSettings>
Then get the key/value pair from the config file and set your service dependency based on the config value.
Test
[TestClass]
public class MyTest
{
IServices _service = null;
[TestInitialize]
public void Setup()
{
var isUnitTest = bool.Parse(ConfigurationManager.AppSettings["IsUnitTest"]);
if (isUnitTest)
{
_service = new MockService();
}
else
{
_service = new Service();
}
}
.
.
.
I disagree C Bauer. No consensus here at all. Mocks and dependency injection go a long way to solving this problem. I've seen this approach used more frequently over the last couple of years and it works fine.
Usually in Agile environments where roles are cross functional. Some teams want a single code base/solution to work from. Especially where the size of the code base is relatively small, having "unit" tests able to function as light weight Integration tests works fine. There is no black and white solution here, only the one that works best for the problem at hand. Regardless of what others say there are multiple ways to approach this problem and the solutions/approaches are growing and changing all the time.

What Is Object Under Test vs. Collaborator here?

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);
}

Unit Testing with DbContext mock through Service Layer

I'm a beginner at writing unit tests and I have a test I'm trying to get working. I'll start of by explaining what I'm trying to test.
I'm trying to test a method which saves messages in a Mvc 4 project. The method is called SaveMessage and is shown below.
namespace ChatProj.Service_Layer
{
public class UserService : IUserService
{
public MessageContext messageContext = new MessageContext();
public UserService()
{
_messageRepository = new MessageRepository(messageContext);
}
private IMessageRepository _messageRepository;
-> public void SaveMessage(Message message)
{
messageContext.Messages.Add(message);
_messageRepository.Save();
}
The _messageRepository.Save in the SaveMessage method is implemented in my DAL layer MessageRepository and looks like this:
public void Save()
{
context.SaveChanges();
}
This way of saving will seem a bit overcomplicated, but I structured the project this way because I didn't want the service layer (IUserService & UserService) to handle operations that could & should (i think) be handled by the Data Access Layer (IMessageRepository & MessageRepository).
Now comes the tricky part. I've been trying to understand how I could unit test this. This is my try:
namespace ChatProj.Tests
{
[TestFixture]
class MessageRepositoryTests
{
[SetUp]
public void Setup()
{
}
[Test]
public void SaveMessage_SaveWorking_VerifyUse()
{
//Arrange
var userServiceMock = new Mock<UserService>();
var message = new Message { MessageID = 0, Name = "Erland", MessageString = "Nunit Test", MessageDate = DateTime.Now };
var repositoryMock = new Mock<IMessageRepository>();
var contextMock = new Mock<MessageContext>();
MessageRepository messageRepository = new MessageRepository(contextMock.Object);
UserService userService = new UserService();
//Act
userService.SaveMessage(message);
//Assert
repositoryMock.Verify(m => m.Save());
userServiceMock.Verify(m => m.SaveMessage(message));
}
}
I get this error: Imgur link , and I'm not quite sure how to solve it. I've tried looking at several other SO posts but I fail to make the test work.
So I'm wondering, how do I practically get my Unit Test to work?
You should setup your MessageContext properties to return fake data and don't make real Db call with SaveChanges method.
Right now it still tries to access a real DB.
But you can setup only virtual properties or if it will be an inteface.
So the best solution is to extract an interface from your MessageContext and inject it into repository. Then you can easily mock your IMessageContext interface and force it to return appropriate in-memory data.
Take a look at these two lines:
UserService userService = new UserService();
//Act
userService.SaveMessage(message);
You're creating a userService instance, and then immediately saving your message. Now jump into the SaveMessage code.
public void SaveMessage(Message message)
{
messageContext.Messages.Add(message);
_messageRepository.Save();
}
Ok, now you're adding stuff to messageContext, and then calling _messageRepository.Save(). But where are messageContext and _messageRepository instantiated?
public MessageContext messageContext = new MessageContext();
public UserService()
{
_messageRepository = new MessageRepository(messageContext);
}
You're creating them at instantiation. The mocks that you've created in your test aren't being used. Instead of creating instances of these objects in the constructor, you might consider passing them into the UserService constructor as arguments. Then, you can pass in mocked instances in your test.

Categories

Resources