I am using NUnit Testing Framework for the first time and whenever I Run Tests for my code it only passes Assert.False commands, while failing every Assert.True I use. When i run the test below, only TestNotAreYou() is the only one that passes. Is my code wrong or do I have a technical problem?
Code:
using System;
using NUnit.Framework;
using System.Collections.Generic;
namespace Week22
{
[TestFixture]
public class Test
{
private IdentifiableObject id;
[SetUp]
public void SetUp()
{
id = new IdentifiableObject(new string[] { "fred", "bob" });
}
[Test]
public void TestAreYou()
{
IdentifiableObject id = new IdentifiableObject(new string[] { "fred", "bob" });
Assert.True(id.AreYou("fred"));
Assert.True(id.AreYou("bob"));
}
[Test]
public void TestNotAreYou()
{
IdentifiableObject id = new IdentifiableObject(new string[] { "fred", "bob" });
Assert.False(id.AreYou("wilma"));
Assert.False(id.AreYou("boby"));
}
[Test]
public void TestCaseSens()
{
IdentifiableObject id = new IdentifiableObject(new string[] { "fred", "bob" });
Assert.True(id.AreYou("fred"));
Assert.True(id.AreYou("bob"));
Assert.True(id.AreYou("Fred"));
Assert.True(id.AreYou("bOB"));
}
[Test]
public void TestFirstID()
{
IdentifiableObject id = new IdentifiableObject(new string[] { "fred", "bob" });
Assert.True(id.FirstID == "fred");
}
[Test]
public void TestAddID()
{
IdentifiableObject id = new IdentifiableObject(new string[] { "fred", "bob" });
id.AddIdentifier("wilma");
Assert.True(id.AreYou("fred"));
Assert.True(id.AreYou("bob"));
Assert.True(id.AreYou("wilma"));
}
}
}
Program thats being tested:
using System.Linq;
using System;
using System.Collections.Generic;
using System.Text;
namespace Week22
{
public class IdentifiableObject
{
private List<string> _identifiers = new List<string>();
public IdentifiableObject(string[] idents)
{
Array.ForEach(idents, s => AddIdentifier("true"));
}
public bool AreYou(string id)
{
return _identifiers.Contains(id.ToLower());
}
public string FirstID
{
get
{
return _identifiers.First();
}
}
public void AddIdentifier(string id)
{
_identifiers.Add(id.ToLower());
}
}
}
This has nothing to do with unit tests. In your code, you're iterating over the identifiers:
Array.ForEach(idents, s => AddIdentifier("true"));
You're adding the string "true" for each identifier. Instead add s.
You can debug unit tests. Then set a breakpoint and step through your code to inspect your variables.
your method public void AddIdentifier(string id) I believe is only ever adding "true" maybe try replacing
public IdentifiableObject(string[] idents)
{
Array.ForEach(idents, s => AddIdentifier("true"));
}
with
public IdentifiableObject(string[] idents)
{
Array.ForEach(idents, s => AddIdentifier(s));
}
I guess you should pass s to the function, not "true".
here: Array.ForEach(idents, s => AddIdentifier("true"));
should be: Array.ForEach(idents, s => AddIdentifier(s));
Related
I have a question to which I basically know the answer.I would like to know why is newly created List<int> empty, how come it's empty even though I filled it with values? I could do it easily to create inside class Vysvedceni(ReportCard) list and then in Main class that I could create a separate field and then just add it to the Dictionary<Enum,List<int>> ...
Something like that:
List<Enum,List<int>> array = new ...
array.Add(1);
array.Add(2);
array.Add(5);
dic[Subject].Add(array);
But I wanted to do it differently:
Student student = new Student("Jan", "Novak",new Vysvedceni());
student.Vysvedceni.Znamky.Add(Vysvedceni.Subjects.math, new List<int>() {1,1,2,3,4,3});
My goal is simple, print Dictionary with Student and his/her marks.
My native language is not English, I wanted to translate the code, but I'm afraid I'll make a mess of it if you copy the code. At least I've added a small translation.
I've also added my comment where problem is or what methods do.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Cviceni1412
{
class Student
{
private string jmeno; //Name
private string prijmeni; //Surname
private Vysvedceni vysvedceni;
//Dictionary<List<Student>, List<Vysvedceni>> vysvedceniTridy = new Dictionary<List<Student>, List<Vysvedceni>>();
List<Student> studenti = new List<Student>();
public void SetridStudenty()
{
var setrid = (from student in studenti select student)
.GroupBy(student => student.Jmeno.First()).ToList();
foreach (var item in setrid)
{
Console.WriteLine(item);
}
}
public override string ToString()
{
return "jmeno:"+jmeno + ",prijmeni:" + prijmeni;
}
public Student(string jmeno, string prijmeni, Vysvedceni vysvedceni)
{
this.jmeno = jmeno;
this.prijmeni = prijmeni;
this.vysvedceni = vysvedceni;
}
public string Jmeno { get => jmeno; set => jmeno = value; }
public string Prijmeni { get => prijmeni; set => prijmeni = value; }
internal Vysvedceni Vysvedceni { get => vysvedceni; set => vysvedceni = value; }
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
namespace Cviceni1412
{
class Vysvedceni
{
private Dictionary<Enum, List<int>> znamky = new Dictionary<Enum, List<int>>();
private Dictionary<Enum, int> vizo = new Dictionary<Enum, int>();
private Predmety skolniPredmety;
public Dictionary<Enum, List<int>> Znamky { get => znamky; set => znamky = value; }
internal Predmety SkolniPredmety { get => skolniPredmety; set => skolniPredmety = value; }
public Dictionary<Enum, int> Vizo{ get => vizo; set => vizo= value; }
public double Prumer(Enum predmet) //Method for calulating Average and final mark for student
{
double prumerZnamka=Znamky[predmet].Average();
return prumerZnamka ;
}
public void Vypis()//Print List method
{
Znamky.Select(i => $"{i.Key}:{i.Value}").ToList().ForEach(Console.WriteLine);
}
public Vysvedceni()
{
}
public enum Predmety//Subjects like math,Engl,P.E.,Physic
{
matematika,cestina,fyzika,programovani,telocvik,databaze,webovky
}
}
}
//Student class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Cviceni1412
{
class Student
{
private string jmeno;
private string prijmeni;
private Vysvedceni vysvedceni;
//Dictionary<List<Student>, List<Vysvedceni>> vysvedceniTridy = new Dictionary<List<Student>, List<Vysvedceni>>();
List<Student> studenti = new List<Student>();
public void SetridStudenty()//Sort students to the group by their first letter
{
var setrid = (from student in studenti select student)
.GroupBy(student => student.Jmeno.First()).ToList();
foreach (var item in setrid)
{
Console.WriteLine(item);
}
}
public override string ToString()
{
return "jmeno:"+jmeno + ",prijmeni:" + prijmeni;
}
public Student(string jmeno, string prijmeni, Vysvedceni vysvedceni)
{
this.jmeno = jmeno;
this.prijmeni = prijmeni;
this.vysvedceni = vysvedceni;
}
public string Jmeno { get => jmeno; set => jmeno = value; }
public string Prijmeni { get => prijmeni; set => prijmeni = value; }
internal Vysvedceni Vysvedceni { get => vysvedceni; set => vysvedceni = value; }
}
}
//Main class
using System;
using System.Collections.Generic;
using System.Linq;
namespace Cviceni1412
{
class Program
{
static void Main(string[] args)
{
Student student = new Student("Jan","Novák",new Vysvedceni());
student.Vysvedceni.Znamky.Add(Vysvedceni.Predmety.matematika, new List<int>() {1,1,2,3,4,3 });//There is problem,List is declared and filled,but it prints just only Subject and [System.Generics...]
Console.WriteLine(student.Vysvedceni.Znamky.Keys.Count);
student.Vysvedceni.Vypis();
}
}
}
How I solved it.
Problem wasn't with ToString() method,but with Print() method.Linq iterated just Keys.Hope I helped
public void Print(Subjects sub)
{
foreach (var item in marks//dictionary)
{
Console.WriteLine(item.Key);
foreach (var ite in marks[sub])
{
Console.WriteLine(ite);
}
}
}
I'm wondering if I can do a global config for a test. I know that I can compare this object something like that:
x.Should().BeEquivalentTo(y, opt => opt.Excluding(z => z.Member)
But I want all the methods in my test to use this config.
To exclude a member from a specific type, you can create a custom IMemberSelectionRule.
To use that selection rule for all tests, use the static AssertionOptions.AssertEquivalencyUsing in some setup method of your unit testing framework.
Be aware that AssertionOptions.AssertEquivalencyUsing changes static state of Fluent Assertions, so if you're running tests in parallel it should be invoked before any tests are run.
For NUnit that would be [OneTimeSetUp] inside a [SetUpFixture] not inside a namespace.
using FluentAssertions;
using FluentAssertions.Equivalency;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
[SetUpFixture]
public class MySetUpClass
{
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
AssertionOptions.AssertEquivalencyUsing(e => e.Using(new MyNamespace.MyClassSelectionRule()));
}
}
namespace MyNamespace
{
class MyOuterClass
{
public MyInnerClass MemberToInclude { get; set; }
public int MemberToExclude { get; set; }
}
class MyInnerClass
{
public int AnotherMemberToInclude { get; set; }
public int MemberToExclude { get; set; }
}
internal class MyClassSelectionRule : IMemberSelectionRule
{
public bool IncludesMembers => false;
public IEnumerable<SelectedMemberInfo> SelectMembers(IEnumerable<SelectedMemberInfo> selectedMembers, IMemberInfo context, IEquivalencyAssertionOptions config) =>
selectedMembers.Where(e => !(e.DeclaringType.Name == nameof(MyOuterClass) && e.Name == nameof(MyOuterClass.MemberToExclude)));
}
[TestFixture]
public class UnitTest1
{
[Test]
public void Ignore_the_member_MemberToExclude_on_MyOuterClass()
{
var subject = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
AnotherMemberToInclude = 42,
MemberToExclude = 42
},
MemberToExclude = 1
};
var expectation = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
AnotherMemberToInclude = 42,
MemberToExclude = 42
},
MemberToExclude = 2
};
subject.Should().BeEquivalentTo(expectation);
}
[Test]
public void Do_not_ignore_the_member_MemberToExclude_on_MyInnerClass()
{
var subject = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
MemberToExclude = 1
},
};
var expectation = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
MemberToExclude = 2
},
};
Action act = () => subject.Should().BeEquivalentTo(expectation);
act.Should().Throw<AssertionException>();
}
}
}
My test is setup with mocking data like this
var persons = new List<Core.Domain.Person>
{
new Core.Domain.Person { DisplayName = "Coordinator 1", Email="coordinator01#wur.nl", WurAccount = "coord001" },
new Core.Domain.Person { DisplayName = "Coordinator 2", Email="coordinator02#wur.nl", WurAccount = "coord002" }
};
this.mockUnitOfWork.Setup(x => x.Query<Core.Domain.Person>()).Returns(persons.AsQueryable);
In the code to test the persons are retrieved like this
private Dictionary<string, Domain.Person> GetPersons(IEnumerable<string> wurAccounts)
{
var accounts = wurAccounts.ToList();
return this.session.Query<Domain.Person>()
.Where(x => accounts.Contains(x.WurAccount))
.ToDictionary(x => x.WurAccount);
}
When I run the test I get a NullReferenceException here:
at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
at Remotion.Linq.QueryableBase`1.GetEnumerator()
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector)
at Wur.P2G.Core.Services.PersonSynchronizer.GetPersons(IEnumerable`1 wurAccounts) in C:\Projects\P2G\P2G\Sources\Wur.P2G.Core\Services\PersonSynchronizer.cs:line 112
EDIT
I was able to boile it down to this piece of code that still causes the NullReference Exception:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NHibernate;
using NHibernate.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Wur.P2G.Core.Services.Tests
{
public interface IUnitOfWork : IDisposable
{
ISession Session { get; }
IQueryable<T> Query<T>();
void BeginTransaction();
void Commit();
void Rollback();
}
public class Person
{
public virtual string WurAccount { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Email { get; set; }
public virtual bool HasValidEmail => true;
public override string ToString() => WurAccount;
}
[TestClass()]
public class PersonSynchronizerTests
{
private Mock<IUnitOfWork> mockUnitOfWork;
private Mock<ISession> mockSession;
[TestInitialize]
public void Initialize()
{
this.mockUnitOfWork = new Mock<IUnitOfWork>();
this.mockSession = new Mock<ISession>();
this.mockUnitOfWork.Setup(x => x.Session).Returns(this.mockSession.Object);
}
[TestMethod()]
public void GetPersonsTest()
{
var persons = new List<Person>
{
new Person { DisplayName = "Coordinator 1", Email="coordinator01#wur.nl", WurAccount = "coord001" },
new Person { DisplayName = "Coordinator 2", Email="coordinator02#wur.nl", WurAccount = "coord002" }
};
this.mockUnitOfWork.Setup(x => x.Query<Person>()).Returns(persons.AsQueryable);
var wurAccounts = new[] { "coord001", "coord002" };
var accounts = wurAccounts.ToList();
var personsRead = mockSession.Object.Query<Person>()
.Where(x => accounts.Contains(x.WurAccount))
.ToDictionary(x => x.WurAccount);
}
}
}
Some more text because the stupid editor want it from me.
While the error message shows that the problem is related to NHibernate.Linq, None of the code shown so far is related to NHibernate unless there is something you are not showing that is using it.
The code shown so far should work as expected as demonstrated by the following minimal, complete and verifiable example based on the original example provided.
[TestClass]
public class PersonSynchronizerTest {
[TestMethod]
public void PersonSynchronizer_GetPerson_Should_Return_Two() {
//Arrange
var wurAccounts = new[] { "coord001", "coord002" };
var persons = new List<Person> {
new Person { DisplayName = "Coordinator 1", Email="coordinator01#wur.nl", WurAccount = wurAccounts[0] },
new Person { DisplayName = "Coordinator 2", Email="coordinator02#wur.nl", WurAccount = wurAccounts[1] }
};
var mockSession = new Mock<ISession>();
mockSession.Setup(_ => _.Query<Person>()).Returns(persons.AsQueryable); //<-- setup session
var mockUnitOfWork = new Mock<IUnitOfWork>();
mockUnitOfWork.Setup(_ => _.Query<Person>()).Returns(persons.AsQueryable);
mockUnitOfWork.Setup(_ => _.Session).Returns(mockSession.Object); //<-- UoW returns session
var subject = new PersonSynchronizer(mockUnitOfWork.Object);
//Act
var actual = subject.GetPersons(wurAccounts);
//Assert
actual.Should()
.NotBeNull()
.And.HaveCount(wurAccounts.Length);
}
public class PersonSynchronizer {
private IUnitOfWork unitOfWork;
private ISession session;
public PersonSynchronizer(IUnitOfWork uow) {
this.unitOfWork = uow;
this.session = unitOfWork.Session;
}
public Dictionary<string, Person> GetPersons(IEnumerable<string> wurAccounts) {
var accounts = wurAccounts.ToList();
return this.session.Query<Person>()
.Where(x => accounts.Contains(x.WurAccount))
.ToDictionary(x => x.WurAccount);
}
}
public class Person {
public string DisplayName { get; set; }
public string Email { get; set; }
public string WurAccount { get; set; }
}
public interface IUnitOfWork : IDisposable {
ISession Session { get; }
IQueryable<T> Query<T>();
void BeginTransaction();
void Commit();
void Rollback();
}
public interface ISession {
IQueryable<T> Query<T>();
}
}
The snippet above passes as expected when tested.
I suggest reviewing if there are any NHibernate extension methods being called that may be conflicting with the default Linq Extensions, causing the issues encountered.
I have the following code:
public partial class CustomerContactCommunicationValidator : AbstractValidator<CustomerCommunication>
{
public CustomerContactCommunicationValidator()
{
CascadeMode = CascadeMode.StopOnFirstFailure;
RuleFor(x => x.PhoneNumbers).SetCollectionValidator(new FaxPhoneNumberValidator("PhoneNumber"));
RuleFor(x => x.FaxNumbers).SetCollectionValidator(new FaxPhoneNumberValidator("Faxnumbers"));
}
}
public class FaxPhoneNumberValidator : AbstractValidator<string>
{
public FaxPhoneNumberValidator(string collectionName)
{
RuleFor(x => x).Length(0, 35).OverridePropertyName(collectionName);
}
}
PhoneNumbers and FaxNumbers are declared as List.
My unit tests:
[TestMethod]
[TestCategory("ValidationTests")]
public void ShouldHaveErrorWhenPhoneNumberIsLongerThan35Charachters()
{
validator.ShouldHaveValidationErrorFor(x => x.PhoneNumbers, new List<string>() { "123456789012345678901234567890123456111" });
}
[TestMethod]
[TestCategory("ValidationTests")]
public void ShouldNotHaveErrorWhenPhoneNumberIsSmallerThan35Charachters()
{
validator.ShouldNotHaveValidationErrorFor(x => x.PhoneNumbers, new List<string>() { "0032486798563" });
}
The first test fails, the second one does not.
Also when I do a live test, it succeeds on a phone number which is larger than 35 charachters.
I've seen other questions about this: How do you validate against each string in a list using Fluent Validation?
But I really don't see what I'm doing wrong.
Check this example it might clarify all your doubts.
Validation classes:
using FluentValidation;
using System.Collections.Generic;
namespace Test.Validator
{
public class EmailCollection
{
public IEnumerable<string> email { get; set; }
}
public class EmailValidator: AbstractValidator<string>
{
public EmailValidator()
{
RuleFor(x => x).Length(0, 5);
}
}
public class EmailListValidator: AbstractValidator<EmailCollection>
{
public EmailListValidator()
{
RuleFor(x => x.email).SetCollectionValidator(new EmailValidator());
}
}
}
Try to use:
public class CustomerContactCommunicationValidator : AbstractValidator<CustomerCommunication>
{
public CustomerContactCommunicationValidator()
{
RuleForEach(x => x.PhoneNumbers).Length(0, 35);
RuleForEach(x => x.FaxNumbers).Length(0, 35);
}
}
I have the following method in a ViewModel.
public void ViewModelMethod()
{
UserDialogs.Confirm(new ConfirmConfig
{
Message = "Dialog message",
OnConfirm = (result) =>
{
if (result)
{
AnotherService.Method();
}
}
});
}
In my tests I have the UserDialogsMock and AnotherServiceMock. I'm trying to setup the UserDialogsMock like below.
UserDialogsMock.Setup(s => s.Confirm(It.IsAny<ConfirmConfig>()))
.Callback((ConfirmConfig confirmConfig) => confirmConfig.OnConfirm(true));
How to verify that AnotherServiceMock.Method is invoked?
If AnotherServiceMock is injected, just verify it as normal:
AnotherServiceMock.Verify(s => s.Method(), Times.Once());
Here's a SSCCE that works for me:
namespace ConsoleApplication
{
using System;
using Moq;
using NUnit.Framework;
public class MoqCallbackTest
{
[Test]
public void TestMethod()
{
Mock<IAnotherService> mockAnotherService = new Mock<IAnotherService>();
Mock<IUserDialogs> mockUserDialogs = new Mock<IUserDialogs>();
mockUserDialogs.Setup(s => s.Confirm(It.IsAny<ConfirmConfig>()))
.Callback((ConfirmConfig confirmConfig) => confirmConfig.OnConfirm(true));
SystemUnderTest systemUnderTest = new SystemUnderTest(mockUserDialogs.Object,
mockAnotherService.Object);
systemUnderTest.ViewModelMethod();
mockAnotherService.Verify(p => p.Method(), Times.Never());
}
public interface IAnotherService
{
void Method();
}
public interface IUserDialogs
{
void Confirm(ConfirmConfig config);
}
public class ConfirmConfig
{
public Action<bool> OnConfirm { get; set; }
}
public class SystemUnderTest
{
readonly IAnotherService anotherService;
readonly IUserDialogs userDialogs;
public SystemUnderTest(IUserDialogs userDialogs, IAnotherService anotherService)
{
this.userDialogs = userDialogs;
this.anotherService = anotherService;
}
public void ViewModelMethod()
{
userDialogs.Confirm(new ConfirmConfig { OnConfirm = result =>
{
if (result)
anotherService.Method();
} });
}
}
}
}