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.
Related
I am new with c# controllers and I am trying to join two entities with a LINQ query. But I am getting a 'missing a cast' error message as shown below that I don't understand and it does not help me to correct the error.
The controller looks like:
public class SoonDueReportsController_simple : BaseODataController
{
public SoonDueReportsController_simple(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
public SoonDueReportsController_simple Get()
{
var falligkeiten = UnitOfWork.GetAll<Fälligkeiten>();
var betriebe = UnitOfWork.GetAll<Betriebe>();
var query = (from betrieb in betriebe.AsQueryable()
join fallig in falligkeiten.AsQueryable()
on betrieb.ID equals
fallig.Betrieb_ID
where fallig.Fälligkeit_Erledigt_Datum == null
&& betrieb.Aktiv == true
select new
{
BetriebId = betrieb.ID,
FalligkeitObject = fallig.Fälligkeit_Objekt
});
return query;
}
}
This type of controller I have used with success for single entities (tables from an sql db) to display static data in a kendo grid. But I fail when I try to join two tables as shown above. If someone could help me with this problem I'd appreciate it very much.
Regards, Manu
You select a collection of anonymous objects
select new
{
BetriebId = betrieb.ID,
FalligkeitObject = fallig.Fälligkeit_Objekt
});
And want the method to return a instance of certain type. C# is the strongly typed language without type inference, which means you have to specifically create objects of a certain type or interface if you want to return them.
Also, you are have the controller type itself to be returned from the Get method. This makes no sense. I actually do not know what you want to do but may be this would work:
public class SoonDueReportsController_simple : BaseODataController
{
public SoonDueReportsController_simple(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
public IQueryable<SomeModel> Get()
{
var falligkeiten = UnitOfWork.GetAll<Fälligkeiten>();
var betriebe = UnitOfWork.GetAll<Betriebe>();
var query = (from betrieb in betriebe.AsQueryable()
join fallig in falligkeiten.AsQueryable()
on betrieb.ID equals
fallig.Betrieb_ID
where fallig.Fälligkeit_Erledigt_Datum == null
&& betrieb.Aktiv == true
select new SomeModel
{
BetriebId = betrieb.ID,
FalligkeitObject = fallig.Fälligkeit_Objekt
});
return query;
}
}
public class SomeModel
{
public int BetriebId { get; set; }
public string FalligkeitObject { get; set; }
}
Please bear in mind that there are no such things as "C# controllers". You are working with OData, so I would recommend you to look at some OData resources, there are plenty of examples out there.
And one last thing, don't get me wrong, but it does not help giving properties, types and other identifiers German names. People would have hard time trying to understand your code.
The exception explains to you the problem exactly. You're wanting to return a type of 'SoonDueReportsController_simple' and yet you are returning a Queryable where a' is your new { ..., ... } object.
I like the suggestion given to make a strong typed object and fill it but you can also return a dynamic type.
This code works to explain:
private dynamic Get() => new { Name = "SomeName", Age = 31 };
private void TestGet()
{
var obj = Get();
var name = obj.Name;
var age = obj.Age;
}
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}";
I've been searching the web for a way to make an IEnumerable in the Setup of a Mock by converting the Values of my IDictionary to it (either directly or conversion from '=List to IEnumerable). However I have only come across the latter.
Inspiration Sources:
IEnumerable<object> a = new IEnumerable<object>(); Can i do this?
Convert dictionary with List to IEnumerable
Convert dictionary of any type to IEnumerable collection
How to use Moq to return a List of data or values?
public class UserServiceTests
{
private Mock<IUserRepository> _userRep { get; set; }
// fake app repository to get data from
private IDictionary<int, User> _userRepData { get; set; }
private UserService _sut { get; set; }
public UserServiceTests()
{
_userRepData = new Dictionary<int, User>();
_userRep = new Mock<IUserRepository>();
// Been able to create the proper list using:
// List<User> usersList = _userRepData.Values.ToList<User>();
// IEnumerable<User> users = appsList.AsEnumerable();
// So I am looking for away to replicate this in my setup method
// Obviously know the below is not the correct syntax.
_userRep.Setup(r => r.GetUsers()).Returns(() => new IEnumerable<User> {_userRepData.Values.ToList<User>} );
_sut = new UserService(_userRep.Object);
}
[Fact]
public void GetUsers_succeeds_at_getting_all_users_from_repository()
{
User user1 = new User();
User user2 = new User();
_userRepData.Add(1, user1);
_userRepData.Add(2, user2);
IEnumerable<User> users = new User[] { user1, user2 };
_sut.GetUsers().Should().BeSameAs(users); // Note: fluentassertions
}
}
Values already implements IEnumerable<T>.
You can return it directly; you don't need to create anything.
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();
This is my first unit test and wanted some help clearing out my thoughts about the process of writing a unit test.
I wanted to write a test method that will add a new user - using my AddUser method in my library class.
Document doc = new Document();
[TestMethod]
public string AddUser()
{
string name = doc.AddUser("Testing User");
Assert.IsNotNull(name);
}
The error I am getting on build:
Cannot implicitly convert type void to string
This is my AddUser method:
public void AddUser(string newUserName)
{
using (var db = new DataContext())
{
User user = new User()
{
FullName = newUserName,
ID = Guid.NewGuid()
};
db.Users.InsertOnSubmit(user);
db.SubmitChanges();
}
}
Your method does not have a return value:
public void AddUser
^^^^ no return value
So you can't store it into a string:
string name = doc.AddUser("Testing User");
^^^^^^^^^^^ AddUser has no return value
Make sure you return the name from from your AddUser(string newUserName) method.
Replace your method like
public String AddUser(string newUserName)
{
using (var db = new DataContext())
{
User user = new User()
{
FullName = newUserName,
ID = Guid.NewGuid()
};
db.Users.InsertOnSubmit(user);
db.SubmitChanges();
}
return newUserName;
}
AddUser doesn't return anything.
AddUser is written as a method, not a class. Your test attempts to call it like a method, but the method is void, which does not return a value.
Simply speaking you can't assign void to string.
To make it work you can do in 2 ways:
make your method AddUser return string type or add extra parameter to your method and use keyword out for this parameter
hope it help.