I have a class Class1, which has a constructor and few methods. For these methods I'm writing the unit test cases using MSTest. The class looks like this.
class Class1
{
Order order = new Order(); // there is an class Order
public Class1(Order _order)
{
order = _order;
}
public virtual async Task<bool> GetData()
{
if(order != null)
{
//do something
}
else
{
// do something else
}
}
}
Now, I have to write 2 test cases for this GetData() method, when which tests if block and one which tests the else block. I was able to test the if block successfully, but not able to test the else block. The test method which I'm trying to write is as below.
[TestMethod()]
public void GetDataTest()
{
Order order = new Order();
order = null;
var mockService = new Mock<Class1>(order)
{
CallBase = true
};
var result = await mockService.Object.GetData(); // error thrown from here
Assert.IsFalse(result);
}
What I'm trying to do is set the order object to null and pass the null object to the constructor.But this is throwing some error "Ambiguous match found". Clearly passing the null value is not working here. So can anyone tell me any other work around to test the else block.
PS: I need to test both if and else block so that it is included in the code coverage.
If your code is real then actually there is no need to mock service under test.
This works just fine:
[TestMethod]
public async Task GetDataTest()
{
//Arrange
Order order = null;
var c1 = new Class1(order);
//Act
var result = await c1.GetData();
//Assert
Assert.IsFalse(result);
}
Well, the unit test case and the code which you have shared doesn't have any issue
Except
You are not returning a task, and the error "ambiguous match found" looks like coming from inside the code which is written inside else block.
Try to change your GetData() method as :
public virtual async Task<bool> GetData()
{
TaskCompletionSource<bool> ts = new TaskCompletionSource<bool>();
if (order != null)
{
//do something
ts.SetResult(true);
}
else
{
// do something else
ts.SetResult(false);
}
return await ts.Task;
}
You must return from "GetData()"
public virtual async Task<bool> GetData()
{
if(order != null)
{
//do something
}
else
{
// do something else
}
//return task here with await keyword;
}
Related
I am testing my viewModel which contains a method that comes from a dependency injection, but does not enter the method, I honestly do not know what I am doing wrong.
my test.
[TestCase("5")]
[TestCase("10")]
[TestCase("-1")]
[TestCase("0")]
[TestCase("100")]
//[TearDown]
[Test]
public async Task Deve_Obter_A_Lista_De_Herois_Dado_A_Quantidade_Menor_Ou_Igual_A_100_E_Maior_Que_Zero(string quantidadeHerois)
{
//Arrang
var mockRepo = new Mock<IHeroes>();
ListHeroesViewViewModel listHeroesViewViewModel = new ListHeroesViewViewModel(null, mockRepo.Object);
//action
await listHeroesViewViewModel.GetHeroes(quantidadeHerois);
//assert
if(quantidadeHerois.Equals("5"))
Assert.AreEqual(5, listHeroesViewViewModel.Herois.Count);
else if (quantidadeHerois.Equals("10"))
Assert.AreEqual(10, listHeroesViewViewModel.Herois.Count);
else
Assert.AreEqual(100, listHeroesViewViewModel.Herois.Count);
}
my viewmodel
public async Task GetHeroes(string limit)
{
try
{
IsBusy = true;
///
////in this point it does not enter the method and returns null////
///
var heroes = await _heroes.GetHeroes(limit);
if (heroes.data != null)
Herois = new ObservableCollection<Result>(heroes.data.results);
}
catch (Exception ex)
{
await App.Current.MainPage.DisplayAlert("Atenção", $"Error:{ex.Message}", "Ok");
}
finally
{
IsBusy = false;
}
}
constructor viewModel
public ListHeroesViewViewModel(INavigationService navigationService, IHeroes heroes) : base(navigationService)
{
_navigation = navigationService;
//
///here he receives the dependency caused by mock.object
//
_heroes = heroes;
Title = "Heroes";
}
I don't know what I could be doing wrong, thank you for understanding this is my first test
By default a mock will return default values, which means for class types you get null.
If you want to return something you need to set it up.
Here is an example of a setup that is saying whenever something calls method GetHeroes return new Hero().
var mockRepo = new Mock<IHeroes>();
mockRepo.Setup(x => x.GetHeroes(It.IsAny<string>())).Returns(new Hero());
This is a simple setup, you can make it as complex as you want.
You can find more info here on how mocking works.
There is a way to get the result returned from a method called into a mocked object?
For example, if I have the following classes and an interface:
DoSomethingClass.cs
public class DoSomethingClass
{
IInternalClass _intClass;
public DoSomethingClass(IInternalClass intClass)
{
_intClass = intClass;
}
void DoSomething(int number)
{
// do some transformation to the number, e.g.
var transformedNumber = number * (number - 1);
var x = _intClass.IsEven(transformedNumber);
// do something else
}
}
InternalClass.cs
public interface IInternalClass
{
bool IsEven(int number);
}
public class InternalClass: IInternalClass
{
public InternalClass();
public bool IsEven(int number)
{
return number % 2 == 0;
}
}
And a test class:
Tests.cs
public class Tests
{
[Fact]
public async Task test_something()
{
//PREPARE
var request = 10
var internalMock = new Mock<IInternalClass>();
var classToTest = new DoSomethingClass(internalMock.Object);
// ACT
await classToTest.DoSomething(request);
//ASSERT
//Here I want to check if the method IsEven of the internal class return the right result
}
}
}
What I want to assert is the return value of the method IsEven of the InternalClass called inside the main method DoSomething, there is no way that I can know the transformedNumber calculated inside this method and passed to IsEven.
NOTE: I use the Moq library to mock object.
Excuse me for the stupid example above, but I don't have any simple real code to show here, however I hope this can be sufficient to understand the question.
I am assuming that you want to verify that your IsEven method is called on the mocked IInternalClass?
If that is the case then you can use the Verify method on the mock as follows:
[Fact]
public void DoSomething_Verify()
{
var request = 10;
var internalMock = new Mock<IInternalClass>();
var classToTest = new DoSomethingClass(internalMock.Object);
classToTest.DoSomething(request);
//Verify that the mock is invoked with the expected value, the expected number of times
internalMock.Verify(v => v.IsEven(90), Times.Once);
//There are lots of other options for Times, e.g. it is never called with an unexpected value maybe.
internalMock.Verify(v => v.IsEven(91), Times.Never);
}
Also to call the DoSomething method with await you would need to change the method signature as follows:
public async Task DoSomethingAsync(int number)
{
// do some transformation to the number, e.g.
var transformedNumber = number * (number - 1);
var x = _intClass.IsEven(transformedNumber);
// do something else
}
Then you can create a unit test like this:
[Fact]
public async void DoSomething_VerifyAsync()
{
var request = 10;
var internalMock = new Mock<IInternalClass>();
var classToTest = new DoSomethingClass(internalMock.Object);
//To call the DoSomething method with await the method needs the async Task and a good convention is to append Async to the name
await classToTest.DoSomethingAsync(request);
//Another slightly more generic option is to verify that the mock was called with and int exactly n Times
internalMock.Verify(v => v.IsEven(It.IsAny<int>()), Times.Exactly(1));
}
I have a class with few methods. For these methods, I'm creating Unit Test cases using MSTest.
public class Class1
{
public virtual async Task<bool> GetData()
{
string var1 ="dsfs", var2 ="eer";
bool retVal = await DoSomething(var1, var2);
// some business logic
return true;
}
public virtual async Task<bool> DoSomething(string var1, string var2)
{
return true;
}
}
The test cases for method GetData() looks like this.
[TestClass()]
public class Class1Test
{
[TestMethod()]
public async Task GetDataTest()
{
var mockService = new Mock<Class1>();
var isTrue = ReturnTrue(); // this function returns true
mockService.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<string>())).Returns(isTrue);
var result = await mockService.Object.GetData();
Assert.IsTrue(result);
}
}
Now, the problem I'm facing is,
var result = await mockService.Object.GetData();
From this line the control doesn't go to the actual GetData() method in Class1. If I remove virtual keyword from the method definition, then the control goes to the method, i.e, if I make the method like this.
public async Task<bool> GetData()
{
bool retVal = await DoSomething(var1, var2);
// some business logic
return true;
}
I need to make this method virtual because, this method is called in some other method say "XYZMethod" and for writing test case "XYZMethod", I had mocked GetData() method there.
So is there anyway I can solve this problem without removing virtual keyword.
PS: Writing interfaces is not an option as this is a very heavy code which I'm working on and introducing Interface at this stage is not practical.
Enable CallBase on the mock so that it will invoke base members that have not been overridden by a setup expectation.
Also use ReturnsAsync when configuring asynchronous mocked members to allow them to flow correctly when invoked.
[TestClass()]
public class Class1Test {
[TestMethod()]
public async Task GetDataTest() {
//Arrange
var mockService = new Mock<Class1>(){
CallBase = true
};
var expected = ReturnTrue(); // this function returns true
mockService
.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<string>()))
.ReturnsAsync(expected);
//Act
var actual = await mockService.Object.GetData();
//Assert
Assert.IsTrue(actual);
}
}
Since I have converted my WCF methods to Async, my unit tests have failed, and I can't figure out the correct syntax to get them to work.
Cllient proxy class
public interface IClientProxy
{
Task DoSomething(CredentialDataList credentialData, string store);
}
service class
public class CredentialSync : ICredentialSync
{
private ICredentialRepository _repository;
private IClientProxy _client;
public CredentialSync()
{
this._repository = new CredentialRepository();
this._client = new ClientProxy();
}
public CredentialSync(ICredentialRepository repository, IClientProxy client)
{
this._repository = repository;
this._client = client;
}
public async Task Synchronise(string payrollNumber)
{
try
{
if (string.IsNullOrEmpty(payrollNumber))
{
.... some code
}
else
{
CredentialDataList credentialData = new CredentialDataList();
List<CredentialData> credentialList = new List<CredentialData>();
// fetch the record from the database
List<GetCredentialData_Result> data = this._repository.GetCredentialData(payrollNumber);
var pinData = this._repository.GetCredentialPinData(payrollNumber);
// get the stores for this employee
var storeList = data.Where(a => a.StoreNumber != null)
.GroupBy(a => a.StoreNumber)
.Select(x => new Store { StoreNumber = x.Key.ToString() }).ToArray();
var credential = this.ExtractCredentialData(data, pinData, payrollNumber);
credentialList.Add(credential);
credentialData.CredentialList = credentialList;
foreach (var store in storeList)
{
//this line causes an Object reference not set to an instance of an object error
await _client.DoSomething(credentialData, store.StoreNumber);
}
}
}
catch (Exception ex)
{
throw new FaultException<Exception>(ex);
}
}
Test Class
/// </summary>
[TestClass]
public class SynchTest
{
private Mock<ICredentialRepository> _mockRepository;
private Mock<IClientProxy> _mockService;
[TestInitialize]
public void Setup()
{
... some setups for repository which work fine
}
[TestMethod]
public async Task SynchroniseData_WithOneEmployee_CallsReplicateService()
{
this._mockService = new Mock<IClientProxy>();
this._mockService.Setup(x=>x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()));
// arrange
string payrollNumber = "1";
CredentialSync service = new CredentialSync(this._mockRepository.Object, this._mockService.Object);
// act
await service.Synchronise(payrollNumber);
// assert
this._mockService.VerifyAll();
}
The error is when ClientProxy.DoSomething is called:
Object reference not set to an instance of an object
The parameters are both fine.
If I convert my ClientProxy.DoSomething method to a synchronous method
(public void DoSomething(...) )the code works fine, but I do need this to be called asynchronously
DoSomething returns null instead of returning a Task, and so you get an exception when awaiting it. You need to specify when building the mock that it should return a Task.
In this case it seems that you can simply return an already completed task using Task.FromResult so the mock setup should look like this:
this._mockService.Setup(...).Returns(Task.FromResult(false));
Beginning with the next version of .Net (4.6) you can use Task.CompletedTask like this:
this._mockService.Setup(...).Returns(Task.CompletedTask);
You can reduce the amount of clutter in the code by using ReturnsAsync
this._mockService.Setup(...).ReturnsAsync(false);
This way you can remove the Task.FromResult part of the code
I think you need to return the Task from the DoSomething mock
this._mockService.Setup(x => x.DoSomething(It.IsAny<CredentialDataList>(), It.IsAny<string>()))
.Returns(Task.FromResult<int>(0));
So I know with TDD you're supposed to write tests first but I can't get my head around how to write a test for the following code. Can someone help me out with at starting point?
private string GetWMIProperty(string property)
{
string value = string.Empty;
SelectQuery selectQuery = new SelectQuery("Win32_OperatingSystem");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery))
{
foreach (ManagementObject mo in searcher.Get())
{
value = mo[property].ToString();
}
}
return value;
}
You'd just write tests for the method's various outcomes, and in doing so you'd define the method's expected behaviour without actually writing the method yet:
[TestMethod]
public MyClass_GetWMIProperty_GivenGoodInput_ReturnsString()
{
var myClass = new MyClass();
var result = myClass.GetWMIProperty("goodinput");
Assert.IsNotNull(result);
}
[TestMethod]
public MyClass_GetWMIProperty_GivenNullInput_ThrowsArgumentNullException()
{
var myClass = new MyClass();
try
{
var result = myClass.GetWMIProperty(null);
}
catch (ArgumentNullException)
{
// Good
return;
}
// Exception not thrown
Assert.Fail();
}
[TestMethod]
public MyClass_GetWMIProperty_GivenBadInput_ReturnsNull()
{
var myClass = new MyClass();
var result = myClass.GetWMIProperty("badinput");
Assert.IsNull(result);
}
Your method would be stubbed as follows:
// Note public/internal so tests can see it
public string GetWMIProperty(string property)
{
// Stubbed
throw new NotImplementedException();
}
These 3 test methods will fail in this state, because NotImplementedException will be thrown and not caught by any of them.
Next you'd write the actual meat of the method so that you can call it in these tests and they'd all pass. The core idea of TDD is that the tests define the behaviour. Here we have defined:
good input returns a string
bad input returns null
null input throws an ArgumentNullException.