How to Moq DataFactoryManagementClient in Nunit? - c#

net core project. I have one method as below in my repository.
public DataFactoryManagementClient InitiateConnection(AuthenticationConfig authenticationConfig);
I am calling above method in my business layer.
public async Task<List<MyList>> MyMethod(IEnumerable<FileEntity> fileEntities)
{
DataFactoryManagementClient dataFactoryManagementClient = azureDataFactoryRepository.InitiateConnection(_authenticationConfig);
//rest of the code
}
Now I am writing unit test case for the above method.
[Test]
public async Task Mytest()
{
azureDataFactoryRepository.Setup(
x => x.InitiateConnection(
It.IsAny<AuthenticationConfig>())).Returns(new DataFactoryManagementClient());
//rest of the code
}
In the above code I am returning new DataFactoryManagementClient() but it says error Datafactorymanagementclient.Datafactorymanagementclient(params DelegateHandler[])) inaccsible due to its protection level. So I am just confused whether I am doing right thing or not? can someone help me to fix this? Any help would be appreciated. Thank you

You can use IDataFactoryManagementClient as a return type from InitiateConnection method and in the setup (test method) you return the mock of IDataFactoryManagementClient by following code:
[Test]
public async Task Mytest()
{
var dataFactoryManagementClientMock = new Mock<IDataFactoryManagementClient>();
azureDataFactoryRepository.Setup(
x => x.InitiateConnection(
It.IsAny<AuthenticationConfig>())).Returns(dataFactoryManagementClientMock.Object);
//rest of the code
}

Related

How to mock FluentValidation ValidationResults in test

This is the method that I want to test:
public async Task<object> CreateExpense(CreateExpenseCommand command)
{
var validationResults = await _validator.ValidateAsync(command);
if (!validationResults.IsValid)
{
return validationResults.Errors.First().ToString();
}
//more code that is irrelevant for this post
}
To test this, I need to mock _validatior, which is defined as private readonly IValidator<CreateExpenseCommand> _validator; and is used through constructor injection.
I am using AutoFixture with AutoMoqCustomizations and Moq for mocking. Maybe I should use Moq exclusively?
This is what I try to do in the test:
[Fact]
public async Task CreateExpense_Success()
{
//Arrange
var service = _fixture.Fixture.Freeze<Mock<IValidator<CreateExpenseCommand>>>();
service.Setup(x => x.Validate((CreateExpenseCommand)It.IsAny<IValidator<CreateExpenseCommand>>())).Returns(It.IsAny<ValidationResult>);
//more code that is irrelevant for this post
}
However, this results in error:
System.NullReferenceException: 'Object reference not set to instance of an object'.
The error is pretty self-explanatory, but I don't know how to mock correctly.
Image of error:
You need to return an object when doing the setup:
service.Setup(x => x.Validate(It.IsAny<IValidator<CreateExpenseCommand>>()))
.Returns(<*1>);
*1 - Here return the object that you wish to be returned when you call ValidateAsync function. Don't do It.IsAny as it returns null which causes the NullReferenceException.
Also, you need to add virtual to the ValidateAsync method in order to let it be overridable.

Difficulties using InlineData in Unit Test - parameter is a controller

I am new to testing and am now learning to use xUnit.
I have written the below test which works and gives the results I am looking for, but I think that I should be able to make it cleaner, like when using TestCase in nUnit. Therefore I am trying to use InlineData, which I understand is xUnits "TestCase", but I don't know how to do it.
When trying to set it up, as shown below (please see the outcommented lines), then it tells me
[Theory]
// [InlineData("")] // wanna use InlineData just to make the code/test cleaner.
// [InlineData(null)]
public async Task Get_Return_Something(
MyController sut)
{
var result1 = await sut.Get(""); // when placing "sut" as param, I get: cannot convert from MyController to string.
var result2 = await sut.Get(null); // same applies here..
result1.ShouldBeOfType(typeof(OkObjectResult));
result2.ShouldBeOfType(typeof(BadRequestObjectResult));
}
My question is - how do I implement the InlineData so that the test is cleaner. And is it even possible when I have a controller as a parameter?
Just to clarify it -> should there be a way to use the syntax from nUnit:
// something like this
[TestCase("", OkObjectResult)]
[TestCase(null, BadRequestObjectResult)]
public async Task Get_Return_Something(MyController sut, param1, param2)
{
var result = await.sut.Get(param1);
result.ShouldBeOfType(typeof(param2));
}
Maybe the nUnit example is incorrect - but I'm trying to point out, what I am looking for, by saying cleaner code. By following the TestCase-logic, I can easily expand my test to 10-15 different TestCases. And I've heard that xUnit does something similar with InlineData (which LasseVågsætherKarlsen told me wasn't possible) - or then MemberClass or ClassData.
Possibility 1
Create a MyControllerClassData
public class MyControllerClassData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] {
new MyController
{
Id = 1,
// ...
}
};
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
Modify your Theory
[Theory]
[ClassData(typeof(MyControllerClassData))]
public async Task Get_Return_Something(MyController sut)
{
var result1 = await sut.Get(""); // when placing "sut" as param, I get: cannot convert from MyController to string.
var result2 = await sut.Get(null); // same applies here..
result1.ShouldBeOfType(typeof(OkObjectResult));
result2.ShouldBeOfType(typeof(BadRequestObjectResult));
}
Possibility 2
Create the MyController class in the constructor and store it on a private property
Change the parameters to string and the objectResult that you want
Use always the same MyController, use the string to do the Get() and validate it against the objectResult expected.
This solution seems a lit bit cleaner, as you have one test for each situation.
Finally I managed to get it fixed. It IS actually possible to use InlineData - just not as easy (imo) as with nUnit. Here is the solution:
[Theory]
[InlineData("", typeof(OkObjectResult))]
[InlineData(null, typeof(BadRequestObjectResult))]
public async Task Get_Return_Something(param1, param2){
// moq MyController with its parameters/objects
...
var result = await sut.Get(param1);
result.ShouldBeOfType(param2);
}
In my opinion a very easy way to do it - compared to the ones found when searching the net - hope it is useful for other too.

Mocking Request.UserHostAddress for Unit Testing for WEB API

I am writing Unit Test for my WEB API Service. I want to mock request from ip address. I am using Microsoft Unit Test.
[TestClass]
public class UnitTest1
{
private Mock<HttpContextBase> moqContext;
private Mock<HttpRequestBase> moqRequest;
[TestMethod()]
public void TestMethod1()
{
var controller = new TestController();
controller.ControllerContext = new ControllerContext(moqContext.Object, new System.Web.Routing.RouteData(), controller);
}
[TestInitialize]
public void SetupTests()
{
// Setup Moq
moqContext = new Mock<HttpContextBase>();
moqRequest = new Mock<HttpRequestBase>();
moqContext.Setup(x => x.Request).Returns(moqRequest.Object);
moqContext.Setup(x => x.Request.UserHostAddress).Returns("192.111.1.1");
}
}
I don't know how to proceed further, I am getting below error.
> Severity Code Description Project File Line Suppression State
> Error CS1503 Argument 3: cannot convert from
> 'WebApplication1.Controllers.TestController' to
> 'System.Web.Mvc.ControllerBase' UnitTestProject1
Any help appreciated.
Is MOQ better than Rino, also, alternate ways for avoiding virtual methods for MOQ testing.
Updates
Ok so the Controller is an API Controller as follows
// GET: api/Test
public IEnumerable<string> Get()
{
string s =HttpContext.Current.Request.UserHostAddress;
...Authentication/Authorization based on IP address
return new string[] { s };
}
I want to mock HttpContext.Current.Request.UserHostAddress in my Unit test so as to test different IP address. My question is how to set the mock IP address. I have found a link https://blog.slatner.com/geeky/mocking-request-userhostaddress-in-asp-net-mvc.html. but I couldn't figure out how to use. Any help much appreciated.
Have you tried setting up the mock request object instead?
// moqContext.Setup(x => x.Request.UserHostAddress).Returns("192.111.1.1"); <-- not this
moqRequest.Setup(x => x.UserHostAddress).Returns("192.111.1.1")
It means that your TestControllerclass does not inherit from System.Web.Mvc.ControllerBase. So go back to the definition of your TestController and make sure it looks like
public class TestController: System.Web.Mvc.ControllerBase
{ /* your code here */ }

How to use Microsoft Fakes to Shim Async Task method?

I'm using Microsoft Fakes to Shim an async method that invokes another method to get an implemented DbContext. Because database connection string is not supplied in the Unit Test while the method being invoked inside the async method needs it. Shim will not only skip the method that uses the connection string, but returns a customizable DbContext.
Here is the aysnc method implementation:
public async Task<AccountDataDataContext> GetAccountDataInstance(int accountId)
{
var account = await this.Accounts.FindAsync(accountId);
return AccountDataDataContext.GetInstance(account.AccountDataConnectionString);
}
However, I'm not familiar with Shim async method. What I did look like this:
ConfigurationEntities.Fakes.ShimConfigurationDataContext.AllInstances.GetAccountDataInstanceInt32NullableOfInt32 = (x, y, z) => new Task<AccountDataEntities.AccountDataDataContext>(() =>
{
return new SampleContext();// This is the fake context I created for replacing the AccountDataDataContext.
});
And SampleContext is implementing AccountDataDataContext as follows:
public class SampleContext: AccountDataDataContext
{
public SampleContext()
{
this.Samples = new TestDbSet<Sample>();
var data = new AccountDataRepository();
foreach (var item in data.GetFakeSamples())
{
this.Samples.Add(item);
}
}
}
Below is the code snippet for the test case:
[TestMethod]
public async Task SampleTest()
{
using (ShimsContext.Create())
{
//Arrange
SamplesController controller = ArrangeHelper(1);// This invokes the Shim code pasted in the second block and returns SamplesController object in this test class
var accountId = 1;
var serviceId = 2;
//Act
var response = await controller.GetSamples(accountId, serviceId);// The async method is invoked in the GetSamples(int32, int32) method.
var result = response.ToList();
//Assert
Assert.AreEqual(1, result.Count);
Assert.AreEqual("body 2", result[0].Body);
}
}
As the result, my test case is running forever. I think I might write the Shim lamdas expression completely wrong.
Any suggestion? Thank you.
You don't want to return a new Task. In fact, you should never, ever use the Task constructor. As I describe on my blog, it has no valid use cases at all.
Instead, use Task.FromResult:
ConfigurationEntities.Fakes.ShimConfigurationDataContext.AllInstances.GetAccountDataInstanceInt32NullableOfInt32 =
(x, y, z) => Task.FromResult(new SampleContext());
Task also has several other From* methods that are useful for unit testing (e.g., Task.FromException).

xUnit and Moq do not support async - await keywords

I am trying to discover how to apply the async and await keywords to my xUnit tests. I am using xUnit 1.9 and Async CTP 1.3. Here is my test case
I have an interface which specifies one asynchronous method call
public interface IDoStuffAsync
{
Task AnAsyncMethod(string value);
}
I have a class which consumes the interface and calls the async method
public class UseAnAsyncThing
{
private readonly IDoStuffAsync _doStuffAsync;
public UseAnAsyncThing(IDoStuffAsync doStuffAsync)
{
_doStuffAsync = doStuffAsync;
}
public async Task DoThatAsyncOperation(string theValue)
{
await _doStuffAsync.AnAsyncMethod(theValue);
}
}
In my tests I wish to check that the method DoThatAsyncOperation is calling the method with the correct value so I mock the interface and use the Moq to verify the call
[Fact]
public async void The_test_will_pass_even_though_it_should_fail()
{
var mock = new Mock<IDoStuffAsync>();
var sut = new UseAnAsyncThing(mock.Object);
mock.Setup(x => x.AnAsyncMethod(It.IsAny<string>()));
await sut.DoThatAsyncOperation("test");
// This won't throw a Moq.MockExcpetion so the test appears to pass
// However it does not run
mock.Verify(x => x.AnAsyncMethod("fail"));
}
This test is using the async and await keywords. When it runs it erroneously passes as Moq should assert that the verify fails. Any code after the call to sut.DoThatAsyncOperation("test"); does not run
[Fact]
public void This_will_work_and_assert_the_reslt()
{
var mock = new Mock<IDoStuffAsync>();
var sut = new UseAnAsyncThing(mock.Object);
mock.Setup(x => x.AnAsyncMethod(It.IsAny<string>()));
sut.DoThatAsyncOperation("test").ContinueWith(y => { });
// This won't throw a Moq.MockExcpetion so the test appears to pass
// However it does not run
mock.Verify(x => x.AnAsyncMethod("fail"));
}
This test is setup without the await and async keywords and passes fine.
Is this expected behavior for xUnit and Moq?
Update
Thanks for Stephen's comment I managed to fix the first test by making two changes. The test now returns a Task instead of void and the Mock also returns a Task.
[Fact]
public async Task The_test_will_pass_even_though_it_should_fail()
{
var mock = new Mock<IDoStuffAsync>();
var sut = new UseAnAsyncThing(mock.Object);
mock.Setup(x => x.AnAsyncMethod(It.IsAny<string>())).ReturnAsync(true);
await sut.DoThatAsyncOperation("test");
// This now fails as it should
mock.Verify(x => x.AnAsyncMethod("fail"));
}
Change your unit test method to return Task instead of void, and it should work. Support for async void unit tests is being considered for a future release.
I describe in detail why async unit tests don't work by default on my blog. (My blog examples use MSTest, but the same problems existed in every other test runner, including xUnit pre-1.9).
I tried to use the code from your 'Update', but it was stopping at the async method that I was mocking.
var tcs = new TaskCompletionSource<T>();
tcs.SetResult(default(T));
mock.Setup(x => x.AnAsyncMethod(It.IsAny<T>())).Returns(tcs.Task);
So to fix that I had to change the 'Return' method:
mock.Setup(x => x.AnAsyncMethod(It.IsAny<T>())).Returns(()=> { return tcs.Task; } );

Categories