I have a Employee class with one method which is not implemented
namespace Employee
{
public class Employee
{
public virtual DateTime getDateOfJoining(int id)
{
throw new NotImplementedException();
}
}
}
I want to mock this, and I'm expecting the method to return current DateTime.
namespace Employee.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void getJoiningDateMock()
{
var employee = new Mock<Employee>();
employee.Setup(x => x.getDateOfJoining(It.IsAny<int>())).Returns((int x) => DateTime.Now);
var objEmp = new Employee();
Assert.AreEqual(DateTime.Now, employee.getDateOfJoining(1));
}
}
}
The way I'm invoking Mock is incorrect. What am I missing here, specifically how would I write AssertEquals?
The below only confirms that the mock behaves as it was setup.
[TestClass]
public class UnitTest1 {
[TestMethod]
public void getJoiningDateMock() {
//Arrange
var expected = DateTime.Now;
var employeeMock = new Mock<Employee>();
employeeMock
.Setup(x => x.getDateOfJoining(It.IsAny<int>()))
.Returns(expected);
var objEmp = employeeMock.Object;
//Act
var actual = objEmp.getDateOfJoining(1);
//Assert
Assert.AreEqual(expected, actual);
}
}
Reference : Moq Quickstart
Related
I have such service as below. Let's say i want to test Create() method. I read that in unit testing i should test by comparing, counting and so on. How could i then test my Create() method. Is it ugly to change return type from void Create to bool Create just to be able to check method output for testing purpose or that's not ideal idea? Can you propose something?
public class CreateCarService : ICreateCarService
{
private readonly ICarQuery _carQuery;
private readonly ICarRepository _carRepository;
public CreateCarService(ICarQuery carQuery, ICarRepository carRepository)
{
_carQuery = carQuery;
_carRepository = carRepository;
}
public void Create(Car car)
{
if (car == null) throw new CusException(Error, "Car object cannot be null");
if (_carQuery.IsLoginExist(car.Login))
throw new CusException(Error, "Message1");
if (_carQuery.IsEmailExist(car.Email))
throw new CusException(Error, "Message1");
_carRepository.Add(car);
}
}
You might verify that for any valid Car instance Add method was called only once, by setting up the Moq behavior of IsLoginExist and IsEmailExist method an using a Verify method
[TestFixture]
public class Test
{
[Test]
public void CreateCarServiceTest()
{
var carQueryMock = new Mock<ICarQuery>();
var carRepositoryMock = new Mock<ICarRepository>();
var createCarService = new CreateCarService(carQueryMock.Object, carRepositoryMock.Object);
carQueryMock.Setup(c => c.IsLoginExist(It.IsAny<string>())).Returns(false);
carQueryMock.Setup(c => c.IsEmailExist(It.IsAny<string>())).Returns(false);
createCarService.Create(new Car());
carRepositoryMock.Verify(c => c.Add(It.IsAny<Car>()), Times.Once);
}
}
It also makes sense to check a negative cases, when Create method throws an exception
[Test]
public void CreateCarNegativeTest()
{
var carQueryMock = new Mock<ICarQuery>();
var carRepositoryMock = new Mock<ICarRepository>();
var createCarService = new CreateCarService(carQueryMock.Object, carRepositoryMock.Object);
Assert.Throws<CusException>(() => createCarService.Create(null));
carQueryMock.Setup(c => c.IsLoginExist(It.IsAny<string>())).Returns(true);
Assert.Throws<CusException>(() => createCarService.Create(new Car()));
carQueryMock.Setup(c => c.IsLoginExist(It.IsAny<string>())).Returns(false);
carQueryMock.Setup(c => c.IsEmailExist(It.IsAny<string>())).Returns(true);
Assert.Throws<CusException>(() => createCarService.Create(new Car()));
}
You can split this method into different tests to have one Assert per test, or pass the parameters to it.
You want to test the "expected behavior" of the member under test. Since the member under test does not return any verifiable output and has a dependency on external abstractions, you should be able to monitor the interaction of the member under test with that external abstractions and verify the expected behavior
One such example
public void CreateCarService_Create_Should_Add_Car() {
//Arrange
Car car = new Car {
Login = "Login",
Email = "Email"
};
ICarQuery carQuery = Mock.Of<ICarQuery>();
ICarRepository carRepository = Mock.Of<ICarRepository>();
ICreateCarService subject = new CreateCarService(carQuery, carRepository);
//Act
subject.Create(car);
//Assert
Mock.Get(carRepository).Verify(_ => _.Add(car), Times.Once);
}
The example above safely navigates through to the end of the member under test but lets say you wanted to test the exception is thrown for the null parameter case.
public void CreateCarService_Create_Should_Throw_CusException_For_Null_Car() {
//Arrange
ICreateCarService subject = new CreateCarService(null, null);
//Act
Action act = ()=> subject.Create(null);
//Assert
var ex = Assert.Throws<CusException>(act);
}
You want to create tests for all the possible paths through the member under test. So take some time and review the subject under test and work out the possible test cases. Arrange the subject to satisfy those cases and exercise those cases to verify the expected behavior.
Reference Moq Quickstart to get a better understanding of how to use the Moq mocking framework.
You don't need to change it to bool, just to test. A simple way you can do this is:
[TestFixture]
public class Test
{
CreateCarService createCarService;
ICarRepository carRepositoryMock;
[Setup]
public void InitializeTest()
{
var carQueryMock = new Mock<ICarQuery>();
carRepositoryMock = new Mock<ICarRepository>();
createCarService = new CreateCarService(carQueryMock.Object, carRepositoryMock.Object);
}
[Test]
public void CreateCarShouldThrowIfNull()
{
//arrange
Car car =null;
//act and assert
Assert.Throw<CustomException>(()=>
{
createCarService.CreateCar(car);
});
}
[Test]
public void CreateCarShouldThrowForInvalidLogin()
{
//arrange
var car = new Car()
{
Login=null,
Email="Email"
};
//act and assert
Assert.Throw<CustomException>(()=>
{
createCarService.CreateCar(car);
});
}
And So on.
You can use Assert.Throw for invalid car objects or Assert.DoesNotThrow for valid car objects. Finally, you can test if the car was added to the repository by:
[Test]
public void CreateCarShouldAddCarToRepo()
{
//arrange
var car = new Car()
{
Login="Login",
Email="Email"
};
//act
createCarService.CreateCar(car);
var carRetrieved =carRepositoryMock.GetCar(car.id);//depending on your implementation
//assert
Assert.AreSame(car,carRetrieved);
}
I was wondering about what is the best practices to write tests if I have multiple implementations per interface.
Have I to replicate each test per implementations or I can create an abstract class that contains all tests about the interface and then create a simple test class per implementation that extends my abstract test class?
I am following "The art of unit testing" written by Osherove and he always repeat that we have to keep tests, and test suites, as simple as we can, so I don't know if adding an abstract class will increase the complexity of read tests by other developers.
Which one of the following example is commonly accepted and more readable?
Sample code:
public interface IMyInterface()
{
public string MyMethod(string input);
}
public class MyClassA : IMyInterface
{
public string MyMethod(string input)
{
return input;
}
}
public class MyClassB : IMyInterface
{
public string MyMethod(string input)
{
return "hello from MyClassB";
}
}
public class MyClassC : IMyInterface
{
public string MyMethod(string input)
{
throw new NotImplementedException();
}
}
TestSuite 1:
[TestFixture]
public class MyClassATest {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
MyClassA sut = new MyClassA();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
[TestFixture]
public MyClassBTest {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
MyClassA sut = new MyClassB();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
[TestFixture]
public MyClassCTest {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
MyClassA sut = new MyClassC();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
TestSuite 2:
[TestFixture]
public abstract class IMyInterfaceTest<TImplementation> where TImplementation : IMyInterface {
[Test]
public void MyMethod_WhenCalled_ReturnsANotNullString()
{
//arrange
TImplementation sut = new MyClassC();
//act
string result = sut.MyMethod("hi");
//assert
Assert.IsNotNull(result);
}
}
[TestFixure]
public class MyClassATest : IMyInterfaceTest<MyClassA> {}
[TestFixure]
public class MyClassATest : IMyInterfaceTest<MyClassB> {}
[TestFixure]
public class MyClassATest : IMyInterfaceTest<MyClassC> {}
Why not try this approach using TestCaseSource (https://github.com/nunit/docs/wiki/TestCaseData). The advantage being you have one test instead of many repeating tests that do the same thing.
[TestCaseSource(typeof(MyDataClass), "TestCases")]
public void MyMethod_WhenCalled_ReturnsANotNullString(IMyInterface sut, string value)
{
//arrange
//act
string result = sut.MyMethod(value);
//assert
Assert.IsNotNull(result);
}
public class MyDataClass
{
public static IEnumerable TestCases
{
get
{
yield return new TestCaseData(new MyClassA(), "hi");
yield return new TestCaseData(new MyClassB(), "test");
yield return new TestCaseData(new MyClassC(), "another");
}
}
}
So I have some initial setup that looks like this:
ILoginManager _loginManager;
Mock<IValidations> _validations;
Mock<IAccountRepository> _accountRepository;
[SetUp]
public void Setup()
{
_loginManager = new LoginManager();
_validations = new Mock<IValidations>();
_accountRepository = new Mock<IAccountRepository>();
}
Then I have the test method that looks like this:
[Test]
public void Login_ValidUser()
{
_validations.Setup(val => val.IsValidAccount(It.IsAny<User>())).Returns(true);
_accountRepository.Setup(repo => repo.Login(It.IsAny<User>())).Returns(()=>new User());
var result = _loginManager.Login(new User());
Assert.That(result, Is.Not.Null);
}
And the actual method that looks like this:
public User Login(User user)
{
if (user != null && _validations.IsValidAccount(user))
{
return _accountDal.Login(user);
}
log.Error("User null or not valid");
return null;
}
The problem is that the test method still calls the original methods so it ignores the mock setup.
Those dependencies would have had to have been injected directly into the manager in order for them to be available for mocking when testing
For example
public class LoginManager : ILoginManager {
private readonly IValidations _validations;
private readonly IAccountRepository _accountDal;
public LoginManager(IValidations validations, IAccountRepository accountDal) {
_validations = validations;
_accountDal = accountDal;
}
public User Login(User user) {
if (user != null && _validations.IsValidAccount(user)) {
return _accountDal.Login(user);
}
log.Error("User null or not valid");
return null;
}
}
Your current example is not using the mocks in the class under test because they were not injected.
Refactor the LoginManager class and the test accordingly
ILoginManager _loginManager;
Mock<IValidations> _validations;
Mock<IAccountRepository> _accountRepository;
[SetUp]
public void Setup() {
_validations = new Mock<IValidations>();
_accountRepository = new Mock<IAccountRepository>();
_loginManager = new LoginManager(_validations.Object, _accountRepository.Object);
}
[Test]
public void Login_ValidUser() {
//Arrange
var expected = new User();
_validations.Setup(val => val.IsValidAccount(It.IsAny<User>())).Returns(true);
_accountRepository.Setup(repo => repo.Login(It.IsAny<User>())).Returns(()=> user);
//Act
var actual = _loginManager.Login(expected);
//Assert
Assert.That(actual, Is.Not.Null);
Assert.AreEqual(expected, actual);
}
I am testing my class
public class myclass
{
private IAwesome awesomeObject;
public myclass(IAwesome awesomeObject)
{
this.awesomeObject = awesomeObject;
}
public void MethodUnderTest()
{
this.awesomeObject.RunSomething(); //I want to verify that RunSomething was called
}
}
The way I am doing this is:
//Arrange
var mockAwesome = new Mock<IAwesome>();
mockAwesome.Setup(x=>x.RunSomething()).Returns ... Verify()...;
//Act
var sut = new myclass(mockAwesome.object);
sut.MethodUnderTest();
//Assert
mockAwesome.Verify();
The exception I am getting is:
System.NotSupportedException : Expression references a method that
does not belong to the mocked object: x => x.RunSomething
Is it not possible to test that a specific method was executed on a mocked object that I passed into a class, that is now part of a private member of that class?
Modify set up line to mockAwesome.Setup(x=>x.RunSomething()).Verifiable() and it should work for the example you provided.
[TestClass]
public class MoqVerificationTest {
[TestMethod]
public void Moq_Should_Verify_Setup() {
//Arrange
var mockAwesome = new Mock<IAwesome>();
mockAwesome.Setup(x => x.RunSomething()).Verifiable();
//Act
var sut = new myclass(mockAwesome.Object);
sut.MethodUnderTest();
//Assert
mockAwesome.Verify();
}
public interface IAwesome {
void RunSomething();
}
public class myclass {
private IAwesome awesomeObject;
public myclass(IAwesome awesomeObject) {
this.awesomeObject = awesomeObject;
}
public void MethodUnderTest() {
this.awesomeObject.RunSomething(); //I want to verify that RunSomething was called
}
}
}
To confirm, comment out this.awesomeObject.RunSomething() in your sample class and run the test again. It will fail because you setup the RunSomething as Verifiable() and it was not used.
When testing, works perfectly fine for me...
Try this approach see if anything different results...
void Main()
{
IAwesome awesome = Mock.Of<IAwesome>();
Mock<IAwesome> mock = Mock.Get(awesome);
mock.Setup(m => m.RunSomething());
MyClass myClass = new MyClass(awesome);
myClass.MethodUnderTest();
mock.Verify(m => m.RunSomething(), Times.Once);
}
public interface IAwesome
{
void RunSomething();
}
public class MyClass
{
private IAwesome awesomeObject;
public myclass(IAwesome awesomeObject)
{
this.awesomeObject = awesomeObject;
}
public void MethodUnderTest()
{
this.awesomeObject.RunSomething();
}
}
I am using Moq library for unit testing. Now what i want is that when I access my object for the first time it should return null, and when i access this on second time it should return something else.
here is my code
var mock = new Mock<IMyClass>();
mock.Setup(?????);
mock.Setup(?????);
var actual = target.Method(mock.object);
in my method i am first checking that whether mock object is null or not, if it is null then do initialize it and then do some calls on it.
bool Method(IMyClass myObj)
{
if (myObj != null)
return true;
else
{
myObj = new MyClass();
bool result = myObj.SomeFunctionReturningBool();
return result;
}
}
what to do setup for mock object,
Also i need to know how to mock this line
bool result = myObj.SomeFunctionReturningBool();
It sounds like you are trying to run two tests with one test method - maybe it would be better to split the tests into two?
You also want to initialise a new object if the method is passed null. To test this, I suggest creating a factory object responsible for creating instances of MyClass. The new code would look like:
interface IMyClassFactory
{
IMyClass CreateMyClass();
}
bool Method(IMyClass myObj, IMyClassFactory myClassFactory)
{
if (myObj != null)
{
return true;
}
myObj = myClassFactory.CreateMyClass();
return myObj.SomeFunctionReturningBool();
}
Then the tests would look like:
[Test]
public void Method_ShouldReturnTrueIfNotPassedNull()
{
Assert.That(target.Method(new MyClass()), Is.True);
}
[Test]
public void Method_ShouldCreateObjectAndReturnResultOfSomeFunctionIfPassedNull()
{
// Arrange
bool expectedResult = false;
var mockMyClass = new Mock<IMyClass>();
mockMyClass.Setup(x => x.SomeFunctionReturningBool()).Returns(expectedResult);
var mockMyFactory = new Mock<IMyClassFactory>();
mockMyFactory.Setup(x => x.CreateMyClass()).Returns(mockMyClass.Object);
// Act
var result = target.Method(null, mockMyFactory.Object);
// Assert
mockMyClass.Verify(x => x.SomeFunctionReturningBool(), Times.Once());
mockMyFactory.Verify(x => x.CreateMyClass(), Times.Once());
Assert.That(result, Is.EqualTo(expectedResult));
}
Here the factory pattern has been used to pass in an object which can create objects of IMyClass type, and then the factory itself has been mocked.
If you do not want to change your method's signature, then create the factory in the class's constructor, and make it accessible via a public property of the class. It can then be overwritten in the test by the mock factory. This is called dependency injection.
Moq - Return null - This working example simply illustrates how to return null using Moq. While the line of code is required is the commented line below, a full working example is provided below.
// _mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
}
public interface IShopService
{
Product GetProduct(string productId);
}
public class ShopService : IShopService
{
public Product GetProduct(string productId)
{
if (string.IsNullOrWhiteSpace(productId))
{
return new Product();
}
return new Product { Id = "8160807887984", Name = "How to return null in Moq" };
}
}
public class Shop
{
private static IShopService _shopService;
public Shop(IShopService shopService)
{
_shopService = shopService;
}
public Product GetProduct(string productId)
{
Product product = _shopService.GetProduct(productId);
return product;
}
}
[TestClass]
public class ShopTests
{
Mock<IShopService> _mockShopService;
[TestInitialize]
public void Setup()
{
_mockShopService = new Mock<IShopService>();
}
[TestMethod]
public void ShopService_GetProduct_Returns_null()
{
//Arrange
Shop shop = new Shop(_mockShopService.Object);
//This is how we return null --- all other code above is to bring this line of code home
_mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);
//Act
var actual = shop.GetProduct(It.IsAny<string>());
//Assert
Assert.IsNull(actual);
}
}
To mock a result value you can do simply:
mock.Setup(foo => foo.SomeFunctionReturningBool()).Returns(true); // or false :)
for the other question, just pass null in the unit test instead of passing mock.object and your unit test cover that too. So you basically create two unit test one with:
var actual = target.Method(mock.object);
and the other one with:
var actual = target.Method(null);
Currently your SUT is tight-coupled with MyClass implementation. You can't mock objects which are instantiated with new keyword inside your SUT. Thus you cannot test your SUT in isolation, and your test is not unit test anymore. When implementation of MyClass.SomeFunctionReturningBool will change (it will return true instead of false), tests of your SUT will fail. This shouldn't happen. Thus, delegate creation to some dependency (factory) and inject that dependency to your SUT:
[Test]
public void ShouldReturnTrueWhenMyClassIsNotNull()
{
Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
Mock<IMyClass> myClass = new Mock<IMyClass>();
var foo = new Foo(factory.Object);
Assert.True(foo.Method(myClass.Object));
}
[Test]
public void ShouldCreateNewMyClassAndReturnSomeFunctionValue()
{
bool expected = true;
Mock<IMyClass> myClass = new Mock<IMyClass>();
myClass.Setup(mc => mc.SomeFunctionReturningBool()).Returns(expected);
Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
factory.Setup(f => f.CreateMyClass()).Returns(myClass.Object);
var foo = new Foo(factory.Object);
Assert.That(foo.Method(null), Is.EqualTo(expected));
factory.VerifyAll();
myClass.VerifyAll();
}
BTW assignment new value to method parameter does not affect reference which you passed to method.
Implementation:
public class Foo
{
private IMyClassFactory _factory;
public Foo(IMyClassFactory factory)
{
_factory = factory;
}
public bool Method(IMyClass myObj)
{
if (myObj != null)
return true;
return _factory.CreateMyClass().SomeFunctionReturningBool();
}
}
You can use TestFixture with parameter. this test will run two times and different type value.
using NUnit.Framework;
namespace Project.Tests
{
[TestFixture(1)]
[TestFixture(2)]
public class MyTest
{
private int _intType;
public MyTest(int type)
{
_intType = type;
}
[SetUp]
public void Setup()
{
if (_intType==1)
{
//Mock Return false
}
else
{
//Mock Return Value
}
}
}
}