I have a class with a method that returns an object of type User
public class CustomMembershipProvider : MembershipProvider
{
public virtual User GetUser(string username, string password, string email, bool isApproved)
{
return new User()
{
Name = username
,Password = EncodePassword(password)
,Email = email
,Status = (isApproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente)
// ...
};
}
// ..
}
User is a domain object. Note the Id property with setter as protected:
public class User : IAuditable, IUser
{
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string Email { get; set; }
public virtual UsuarioStatusEnum Status { get; set; }
public virtual string Password { get; set; }
}
Id is protected because it is generated by the database.
Test project
In my Test project I have a Fake repository with a method Store to save/update the object:
public void Store(T obj)
{
if (obj.Id > 0)
_context[obj.Id] = obj;
else
{
var generateId = _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
var stubUser = Mock.Get<T>(obj); // In test, will always mock
stubUser.Setup(s => s.Id).Returns(generateId);
_context.Add(generateId, stubUser.Object);
}
}
In CustomMembershipProvider I have public override MembershipUser CreateUser method that calls the GetUser to create a User.
This way, all I have to do is mock the GetUser method so that the repository can generate the Id
var membershipMoq = new Mock<CustomMembershipProvider>();
membershipMoq.CallBase = true;
membershipMoq
.Setup(p => p.GetUser(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<bool>()))
.Returns<string, string, string, bool>( (username, password, email, isAproved) => {
var moqUser = new Mock<User>();
moqUser.Object.Name = username;
moqUser.Object.Password = password;
moqUser.Object.Email = email;
moqUser.Object.Status = (isAproved ? UsuarioStatusEnum.Ativo : UsuarioStatusEnum.ConfirmacaoPendente);
return moqUser.Object;
});
_membershipProvider = membershipMoq.Object;
Problem
In theory everything is correct. When CreateUser call 'GetUser' to create a user, the user will return Mock filled;
[TestMethod]
public void CreateUser_deve_criar_usuario_no_repositorio()
{
// Act
MembershipCreateStatus status;
var usr = _membershipProvider.CreateUser(
_fixture.Create<string>(),
_fixture.Create<string>(),
_fixture.Create<string>(),
null, null, true, null,
out status);
// usr should have name, email password filled. But not!
// Assert
status.Should().Be(MembershipCreateStatus.Success);
}
The problem is that Email, Name, Password are empty (with default values)!
The way you prepare the mocked user is the problem.
moqUser.Object.Name = username;
will not set the name, unless you have setup the mock properly.
Try this before assigning values to properties:
moqUser.SetupAllProperties();
This method will prepare all properties on the mock to be able to record the assigned value, and replay it later (i.e. to act as real property).
You can also use SetupProperty() method to set up individual properties to be able to record the passed in value.
Another approach is:
var mockUser = Mock.Of<User>( m =>
m.Name == "whatever" &&
m.Email == "someone#example.com");
return mockUser;
I think you are missing purpose of mocking. Mocks used to mock dependencies of class you are testing:
System under test (SUT) should be tested in isolation (i.e. separate from other units). Otherwise errors in dependencies will cause your SUTs tests to fail. Also you should not write tests for mocks. That gives you nothing, because mocks are not production code. Mocks are not executed in your application.
So, you should mock CustomMembershipProvider only if you are testing some unit, which depends on it (BTW it's better to create some abstraction like interface ICustomMembershipProvider to depend on).
Or, if you are writing tests for CustomMembershipProvider class, then it should not be mocked - only dependencies of this provider should be mocked.
Specifies that the all properties on the mock should have "property behavior",
meaning that setting their value will cause them to be saved and later returned when the properties is requested.
(This is also known as "stubbing".)
The default value for each property will be the one generated as specified by the
property for the mock.
mock.SetupAllProperties();
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");
So I am trying again using a different controller to test a Cocoa desktop application using NUnit and Moq. The problem is, even after the .add() operation, I still don't have what I just added using the mock. More exactly, this is how I do the mock:
User user = new User
{
email = "test#gmail.com",
password = "1",
firstName = "Test",
lastName = "Test"
};
List<User> dataSource = new List<User>();
var userServiceMock = new Mock<IUserService>(MockBehavior.Strict);
userServiceMock.Setup(x => x.add(It.IsAny<User>()));
userServiceMock.Setup(x => x.getAllUsers()).Returns(dataSource);
var controller = new CreateAccountCoreController(userServiceMock.Object);
//act
controller.submit();
//assert
Assert.That(dataSource.Contains(user));
and in controller is this:
readonly IUserService userService;
public CreateAccountCoreController(IUserService userService)
{
this.userService = userService;
}
public void submit()
{
User user = new User
{
email = "test#gmail.com",
password = "1234",
firstName = "Test",
lastName = "Test",
};
userService.add(user);
List<User> users = userService.getAllUsers();
/*users it is empty here..*/
}
So my test always fails because the list of Users it is empty even after .add operation. Can you help please?
There is no place where you fill dataSource collection and you configure your mock to return it from getAllUsers() mock. So you will always get an empty collection from a method.
Use Callback() method to configure expected behavior:
userServiceMock.Setup(x => x.add(It.IsAny<User>())).Callback((User u) => dataSource.Add(u));
The second problem may be in comparing users in Contains() method. You need to tell Contains what makes two users equal. By default it will use ReferenceEquals which will only call two objects equal if they are the same instance.
Either override Equals and GetHashCode in your User class or define an IEqualityComparer<User> class and pass that to Contains.
If two Users that have the same email are "equal" then the implementation is pretty straightforward:
public override bool Equals(object o)
{
if(o.GetType() != typeof(User))
return false;
return this.email == ((User)o).email;
}
public override int GetHashCode()
{
return email.GetHashCode();
}
You can read more about value equality for a type.
public static LoginResult CreateLoginSuccessResponse(this PortalIdentity user)
{
return new LoginResult(
true,
string.Empty,
user.Roles,
false
);
}
public class PortalIdentity : IdentityUser
{
public string Firstname { get; set; }
public string Lastname { get; set; }
}
This block of code is for creating a success response whenever a user logs in successfully. I am a QA and trying to learn how to write unit tests. I am not sure how to write unit test for "this" keyword
this (in the above context at least) just means it is an extension method.
To test it, new up a PortalIdentity, assign to a variable (bob) and call bob.CreateLoginSuccessResponse():
var bob = new PortalIdentity(you may need parameters here);
var result = bob.CreateLoginSuccessResponse();
If the call to bob.CreateLoginSuccessResponse() doesn't compile, then the extension method is likely in a different namespace. As per the docs, you need to:
In the calling code, add a using directive to specify the namespace
that contains the extension method class.
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}";
Lets say we have a User class
public class User
{
public User() {
Created = DateTime.Now;
Tags = new List<string>();
}
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Created {get;set;}
public IEnumerable<string> Tags {get; private set;}
}
And one might want a user to have an id like [FirstName]/[LastName] so we register an IdConvention like this:
_documentStore
.Conventions
.RegisterIdConvention<User>(
(dbname, commands, user) => user.FirstName +"/" + user.LastName ));
Now lets say you created a new user with a new set of tags attached. You want to store it in RavenDB if the User does not exist. However, if the User does exist you don't want to overwrite the existing Object as you want to keep the initial Created date. Therefore you only update the Tags enumeration with the values of the newly created User.
You might do something like this:
public void AddOrUpdateUser(User newUser) {
using (var session = _documentStore.OpenSession())
{
var existingUser = session.Load<User>("myFirstname/myLastname")
if(user != null) {
existingUser.Tags = user.Tags;
}
else {
session.Store(newUser);
}
session.SaveChanges();
}
}
However, if for some reason I changed my IdConvention, I have had to update the code above as well. Is there a way to reference the IdConvention registered in order to calculate the id for the newUser Object. With this id value you could check wether an item exists or not rather than creating the Id by yourself.
After registering an id convention, the GenerateDocumentKey method will use that convention instead of the default hilo generation scheme.
It needs some parameters, which are easiest to get at if you first cast the IDocumentSession to a real DocumentSession.
var s = ((DocumentSession) session);
var key = s.Conventions.GenerateDocumentKey(s.DatabaseName,
s.DatabaseCommands,
yourEntity);