Imagine I have this class:
public class MyClass
{
public string Id { get; set; }
public string Name { get; set; }
public IList<MyOtherClass> MyOtherClassList { get; set; }
}
And this method on my service layer which I want to unit-test with Moq and xunit:
public IList<MyClass> GetAll()
{
var options = new FindOptions<MyClass>
{
Projection = Builders<MyClass>.Projection
.Exclude(m => m.MyOtherClassList)
};
return MyClassRepository.GetAll(options)
}
And this would be the test:
[Fact]
public void GetAll_Success()
{
//Arrange
List<MyClass> expected = ... ;
var mockMyClassRepository = new Mock<IMyClassRepository>();
mockMyClassRepository.Setup(m => m.GetAll(It.IsAny<FindOptions<MyClass>>())).Returns(expected);
var myClassService = new MyClassService(mockMyClassRepository);
//Act
var result = myClassService.GetAll();
//Assert
Assert.Equal(expected, result);
mockMyClassRepository.Verify(m => m.GetAll(It.IsAny<FindOptions<MyClass>>()), Times.Once);
}
I want to avoid using It.IsAny for the FindOptions and be sure that the findOptions are excluding the MyOtherClassList attribute but I'm not sure how to compare the FindOptions class.
Any suggestion?
Hows this
mockMyClassRepository
.Setup(m => m.GetAll(It.IsAny<FindOptions<MyClass>>()))
.Returns(FindOptions<MyClass> a) =>
{
if (a.MyOtherClass != null || a.MyOtherClass.Length() > 0)
throw new InvalidOperationException();
else
return expected;
});
You can use an expression in the Returns to inspect the provided argument so you can apply what ever filtering you want.
mockMyClassRepository
.Setup(_ => _.GetAll(It.IsAny<FindOptions<MyClass>>()))
.Returns((FindOptions<MyClass> options) => {
var projection = options.Projection;
//...use as desired to filter the expected.
return expected;
});
The same could have been done in a Callback where the expected could be manipulated/altered, again based on the passed argument.
Do note that what ever is done with the passed argument is an implementation concern that applies to what is done by the actual repository, which you are trying to mock.
The only way to be sure that the findOptions are actually excluding the MyOtherClassList attribute would be via an integration test.
If you're looking to be more specific on the .Verify call, you can leave the .Setup call to use It.IsAny, then use additional constrains on the verify call, like this:
mockMyClassRepository.Verify(m => m.GetAll(It.Is<FindOptions<MyClass>>(options =>
options.Projection == .... //whatever logic would return true for your success criteria
)), Times.Once);
Related
I'm trying to actually test my code for once, but mocking has always been (one of) my Achilles Heel(s).
I'm doing some stuff with AD, and want to test without actually touch it. Here's what I'm doing:
var userPrincipalMock = new Mock<UserPrincipal>();
userPrincipalMock.Setup(x => x.SamAccountName).Returns("somesamaccountname");
userPrincipalMock.Setup(x => x.EmployeeId).Returns("anemployeenumber");
But apparently UserPrincipal doesn't wanna give up control of a samaccount name that easily:
Message "Unsupported expression: x => x.SamAccountName\nNon-overridable members (here: Principal.get_SamAccountName) may not be used in setup / verification expressions."
Any of you lovely guys or gals know the right way to go about this?
It is impossible to test methods that aren't marked as virtual. For this reason only interfaces should be mocked. To solve your problem, you can create a wrapper:
interface IUserPrincipalWrapper
{
string SamAccountName { get; set; }
string EmployeeId { get; set; }
void Delete();
... // Add all methods and properties of UserPrincipal that you need
}
class UserPrincipalWrapper : IUserPrincipalWrapper
{
private UserPrincipal Implementation { get; }
UserPrincipalWrapper(UserPrincipal implementation)
{
Implementation = implementation;
}
public string SamAccountName
{
get => Implementation.SamAccountName;
set => Implementation.SamAccountName = value;
}
public string EmployeeId
{
get => Implementation.EmployeeId;
set => Implementation.EmployeeId = value;
}
public void Delete()
{
Implementation.Delete();
}
...
// Call or set everything to Implementation...
// This is needed to create an interface around UserPrincipal, which you can mock
}
// Factory is needed for mocking `new` calls..
// as often times, you don't want to test that either
interface IUserPrincipalFactory
{
IUserPrincipalWrapper Create(PrincipalContext context);
}
class UserPrincipalFactory : IUserPrincipalFactory
{
public IUserPrincipalWrapper Create(PrincipalContext context)
{
var implementation = new UserPrincipal(context);
return new UserPrincipalWrapper(implementation);
}
}
Then in your tests you can mock everything:
// This is your mock
var userPrincipalMock = new Mock<IUserPrincipalWrapper>();
// You need factory for mocking `new UserPrincipal();` calls
var factoryMock = new Mock<IUserPrincipalWrapperFactory>();
factoryMock.Setup(factory => factory.Create(It.IsAny<PrincipalContext>())).Returns(userPrincipalMock.Object);
// Now it works :)
userPrincipalMock.Setup(x => x.SamAccountName).Returns("somesamaccountname");
userPrincipalMock.Setup(x => x.EmployeeId).Returns("anemployeenumber");
I was creating a couple of Unit Tests where I wanted to verify if a method is called with a parameter whose properties I was expecting.
So given this very simple system:
public class Employee
{
public bool IsEmployed { get; set; }
}
public class DataStore
{
public void UpdateEmployee(Employee obj)
{
// Save in DB
}
}
public interface IDataStore
{
void UpdateEmployee(Employee employee);
}
public Employee FireEmployee(IDataStore dataStore, Employee employee)
{
employee.IsEmployed = false;
dataStore.UpdateEmployee(employee);
return employee;
}
I want to verify that the DataStore.UpdateEmployee() method is called when the Employee.IsEmployed property is set to false. So here are two test cases that I believe should accomplish the same thing.
[Test]
public void TestViaVerify()
{
//Arrange
Mock<IDataStore> dataStore = new Mock<IDataStore>();
var robert = new Employee { IsEmployed = true };
//Act
FireEmployee(dataStore.Object, robert);
//Assert
dataStore.Verify(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)), Times.Once);
}
[Test]
public void TestViaSetupVerifyAll()
{
//Arrange
Mock<IDataStore> dataStore = new Mock<IDataStore>();
dataStore.Setup(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)));
var robert = new Employee { IsEmployed = true };
//Act
FireEmployee(dataStore.Object, robert);
//Assert
dataStore.VerifyAll();
}
Given the current code of the system, both test passes as expected.
Now say another developer comes along and accidentally moved the setting of the Employee.IsEmployed = false; after the DataStore.UpdateEmployee() method. Now in that case, I want my tests to fail because the employee will not be marked as unemployed in the DB.
public Employee FireEmployee(IDataStore dataStore, Employee employee)
{
dataStore.UpdateEmployee(employee);
employee.IsEmployed = false;
return employee;
}
Now when I run the test:
TestViaVerify Passes
TestViaSetupVerifyAll Fails
I was expecting both of them to fail but it looks like for the TestViaVerify() method, the lambda in the method is executed at the end of the test wherein the Employee.IsEmployed is already set to false.
Is there a way to accomplish what I want with just using the Verify method? And not have to do Setup...VerifyAll? If there is none I'll just go with TestViaVerifyAll() approach.
To be honest it is been more then 2 years since the last time I was updated with moq source code. Both Verify and VerifyAll are based on that every invocation of the fake instance is being captured(include the parameters).
Verify will looking for method/property invocation and verifies the captured invocations(with their captured parameters) while, VerifyAll will take all the setup methods and do the same as Verify method.
Since the captured parameter is ByRef parameter and if the last paragraph is still relevant you can cause your UTs failed simply by add robert.IsEmployed = true; before invoke Verify/VerifyAll:
[Test]
public void TestViaVerify()
{
....
robert.IsEmployed = true; // will make this UT to failed
//Assert
dataStore.Verify(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)), Times.Once);
}
[Test]
public void TestViaSetupVerifyAll()
{
....
robert.IsEmployed = true; // will make this UT to failed
//Assert
dataStore.VerifyAll();
}
I think that in the past I answered something similar(with more examples), the way I was workaround this problem is a combination between Setup and Callback since I don't like to use VerifyAll pattern:
....
var invokedCorrectly = false;
dataStore.Setup(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)))
.Callback<Employee>(x=> invokedCorrectly = true);
//Act
FireEmployee(dataStore.Object, robert);
//Assert
Assert.IsTrue(invokedCorrectly);
This is expected behavior in moq as arguments captured by invocation are compared by identity, using Equals not by value. Once you changed captured arguments you actually directly change the invocation. Then later on when you verify these objects are not the same anymore. As #Old Fox alredy provided one solution I will just add one more. You could use Verify() instead of VerifyAll() the difference is that the first one will only check setups marked as Verifiable(). In your case something like this:
[Test]
public void TestViaSetupVerifyAll()
{
//Arrange
Mock<IDataStore> dataStore = new Mock<IDataStore>();
dataStore
.Setup(x => x.UpdateEmployee(It.Is<Employee>(e => e.IsEmployed == false)))
.Verifiable();
var robert = new Employee { IsEmployed = true };
//Act
FireEmployee(dataStore.Object, robert);
//Assert
dataStore.Verify();
}
If you mark setup as Verifiable() you could be able to capture the particular invocation with the state of the object you actually expect.
I am trying to write method in AutoMapper class. My situation is as below.
ClinicListVm = AutoMapperConfig.mapper
.Map<GetClinicsByUserName_Result, ClinicListViewModel>(c);
I already map ClinicListViewModel with GetClinicsByUserName_Result now I want to manipulate one attribute my destination model as below.
ClinicListVm.ProgressBarCssClass = string.Empty;
if (ClinicListVm.PercentComplete == 100)
{
ClinicListVm.ProgressBarCssClass = "progress-bar-success";
}
else if (DateTime.Now.Subtract(ClinicListVm.BillerStartDateTime ?? DateTime.Now).TotalDays > MaxDaysInDataEntry)
{
// partial is a warning color
ClinicListVm.ProgressBarCssClass = "progress-bar-partial";
}
So, How I can include this code it self in automapper class.
Thanks
I personally think #Rajmond Burgaj's anwer is a good one. Using a ResolveUsing(), or a custom resolver, is in this case a good way to go.
However, I just want to share a more pragmatic alternative that may result in the same and might help you in the future. You may want to consider abstracting the conditional if...then... logic to a seperate function. For example:
private string DetermineProgressBarState(SourceClass source)
{
if (source.PercentComplete == 100) return "progress-bar-success";
var MaxDaysInDataEntry = 42; // missing in your sample
return DateTime.Now.Subtract(source.BillerStartDateTime ?? DateTime.Now).TotalDays > MaxDaysInDataEntry
? "progress-bar-partial"
: null;
}
With that, you can easily map it in your configuration, like so:
Mapper.Initialize((config =>
{
config.CreateMap<SourceClass, TargetClass>()
.ForMember(
dest => dest.ProgressBarCssClass,
opt => opt.MapFrom(src => DetermineProgressBarState(src))
);
}));
This runs exactly as you'd expect. Here is the full sample, as a XUnit test (but you'll get the picture):
public class SourceClass
{
public int PercentComplete { get; set; }
public DateTime? BillerStartDateTime { get; set; }
}
public class TargetClass
{
public string ProgressBarCssClass { get; set; }
}
public class UnitTest1
{
[Fact]
public void Test1()
{
// arrange - configure the automapper
Mapper.Initialize((config =>
{
config.CreateMap<SourceClass, TargetClass>()
.ForMember(
dest => dest.ProgressBarCssClass,
opt => opt.MapFrom(src => DetermineProgressBarState(src))
);
}));
// arrange - create a
var source = new SourceClass() { PercentComplete = 100 };
// act - map source to target
var target = Mapper.Map<TargetClass>(source);
// assert - verify the result
target.ProgressBarCssClass.Should().Be("progress-bar-success");
}
private string DetermineProgressBarState(SourceClass source)
{
if (source.PercentComplete == 100) return "progress-bar-success";
var MaxDaysInDataEntry = 42; // missing in your sample
return DateTime.Now.Subtract(source.BillerStartDateTime ?? DateTime.Now).TotalDays > MaxDaysInDataEntry
? "progress-bar-partial"
: null;
}
}
But... I totally agree with the comment that AutoMapper is not the place to put this logic in. The reason is that you're actually defining markup logic (html/css data) in your mapping logic. This is better placed inside your view, presumably your .cshtml.
With that in mind, should you choose to refactor this somehow "the proper way" in the future, the DetermineProgressBarState() function will still be helpful. You'll just move the code from your AutoMapper config to your controller (or .cshtml helper).
If you want to execute another function while mapping you can use ResolveUsing method and put your logic in there.
CreateMap<GetClinicsByUserName_Result, ClinicListViewModel>()
.ForMember(d => d.ProgressBarCssClass , o => o.ResolveUsing(s =>
{
//Do your custom logic here.
}))
.AfterMap((src, dest) =>
{
//Do your logical after mapping has been done
dest.ProgressBarCssClass = string.Empty;
if (dest.PercentComplete == 100)
{
dest.ProgressBarCssClass = "progress-bar-success";
}
else if (DateTime.Now.Subtract(dest.BillerStartDateTime ??
DateTime.Now).TotalDays > MaxDaysInDataEntry)
{
// partial is a warning color
dest.ProgressBarCssClass = "progress-bar-partial";
}
});
Not quite sure where that MaxDaysInDataEntry is coming from but if it can be retrieved inside this method your are good to go this way otherwise if MaxDaysInDataEntry is a variable generated from business logic elsewhere then it is a problem!
Anyway let me know if it help and where that variable is coming from!
I'm writing some unit tests and have a class called Account which has
public Guid AccountId {get;set;}
public IEnumerable<string> EmailAddresses {get;set;}
etc...
I want to use autofixture to create the account, but I'm having trouble getting the email format.
I have tried
fixture.Register<string>(() => string.Format("{0}#acme.com", fixture.Create<string>()));
but that that leads to circular problem.
I could do this
fixture.Register<string>(() => string.Format("{0}#acme.com", fixture.Create<int>()));
But I'd rather have a string at the start of the address.
EDIT
Thanks to both answers I have a written up a summary and few other scenarios as a post here - http://nodogmablog.bryanhogan.net/2016/04/customizing-a-specific-string-inside-a-class-using-autofixture/
There are a couple of ways of doing that. Here's one of them:
Assuming that MyClass is defined as
public class MyClass
{
public Guid AccountId { get; set; }
public IEnumerable<string> EmailAddresses { get; set; }
}
Then, a Fixture object can be customized like so
var fixture = new Fixture();
fixture.Customize<MyClass>(c => c
.With(x =>
x.EmailAddresses,
fixture.CreateMany<MailAddress>().Select(x => x.Address)));
var result = fixture.Create<MyClass>();
And so the EmailAddresses will be filled with email strings that look like:
"18e743af-89ae-46b7-b38e-ff51425ec745#example.org"
"928bd85d-7d89-4cca-bff3-a12d5da6fe29#example.org"
"61db1178-8af9-489f-ba44-95c6393d84a9#example.com"
This is one of those situations where AutoFixture is giving you feedback on the usability of your object model.
If the EmailAddresses property is supposed to only contain valid email addresses, then you should ask yourself whether representing them as generic strings is the right choice. A more specific type like the MailAddress class would restrict the set of valid values for that property.
It would also make it easier to generate test data for it, since AutoFixture knows how to create instances of MailAddress.
Having said that, if it's not feasible for you to change the object model, you can still write a customization that tells AutoFixture to provide valid email addresses for any property or parameter of type IEnumerable<string> with email somewhere in their name:
public class EmailAddressStringsGenerator : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (IsEnumerableOfStringPropertyOrParameterNamedEmail(request))
{
return CreateManyEmailAddresses(context);
}
return new NoSpecimen();
}
static bool IsEnumerableOfStringPropertyOrParameterNamedEmail(object request)
{
return IsEnumerableOfStringPropertyNamedEmail(request) ||
IsEnumerableOfStringParameterNamedEmail(request);
}
static bool IsEnumerableOfStringPropertyNamedEmail(object request)
{
var property = request as PropertyInfo;
return property != null &&
property.Name.ContainsIgnoringCase("email") &&
typeof(IEnumerable<string>).IsAssignableFrom(property.PropertyType);
}
static bool IsEnumerableOfStringParameterNamedEmail(object request)
{
var parameter = request as ParameterInfo;
return parameter != null &&
parameter.Name.ContainsIgnoringCase("email") &&
typeof(IEnumerable<string>).IsAssignableFrom(parameter.ParameterType);
}
static IEnumerable<string> CreateManyEmailAddresses(ISpecimenContext context)
{
var addresses = (IEnumerable<MailAddress>)
context.Resolve(typeof(IEnumerable<MailAddress>));
return addresses.Select(a => a.Address);
}
}
You can then use that customization in a Fixture by adding it to the Customizations property:
fixture.Customizations.Insert(0, new EmailAddressStringsGenerator());
From Autofixture
var localPart = fixture.Create<EmailAddressLocalPart>().LocalPart;
var domain = fixture.Create<DomainPart>().Domain;
var fullAddress = $"{localPart}#{domain}";
In my controller action, whenever a new product is added I check in the database that this product no is not present already. The code for this check looks like
public ActionResult Index(ProductModel model)
{
var productCount = _productsService.GetAll(true).Count(x => x.ProductNumber == model.ProductNumber);
if (productCount > 0)
ModelState.AddModelError("ProductNumber", Product already present in the system!");
// more processing
}
I m new to MOQ testing and trying to write a unit test to setup the GetAll method which will return 0. I have written something like this but it does not seem to work
var _productsService = new Mock<IProductsService>();
_productsService.Setup(m => m.GetAll(true).Count()).Returns(0);
Any ideas? thanks
This is not how you use Moq -- Count is most likely not your method (it's LINQ/other 3rd party), you don't mock it. What you need to mock is GetAll method, which is a method on your mockable dependency. You "tell" GetAll to return a product with model matching the parameter, like so:
[Test]
public void Index_ReportsModelError_WhenProductAlreadyExists()
{
const int ExistingProductNumber = 10;
var _productsService = new Mock<IProductsService>();
var existingProduct = new Product { ProductNumber = ExistingProductNumber };
_productsService.Setup(m => m.GetAll(true)).Returns(new [] { existingProduct });
controller.Index(new ProductModel { ProductNumber = ExistingProductNumber });
// Assert
}
Fixing existing tests is as simple as making sure GetAll never returns products with number same as the one in Index parameter:
const int ExistingProductNumber = 10;
const int NewProductNumber = 20;
var _productsService = new Mock<IProductsService>();
var existingProduct = new Product { ProductNumber = ExistingProductNumber };
_productsService.Setup(m => m.GetAll(true)).Returns(new [] { existingProduct });
controller.Index(new ProductModel { ProductNumber = NewProductNumber });
// Assert
Take a look at this post:
Expression references a method that does not belong to the mocked object
He basically has the same problem, you're trying to mock an extension method Count()