1
votes

I have the following ticket repository:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Moq;
using SC.BL.Domain;

namespace SC.DAL
{
  public class TicketRepositoryHC : ITicketRepository
  {
    private List<Ticket> tickets;
    private List<TicketResponse> responses;
    private Mock<IList<Ticket>> ticketsMock;

    public TicketRepositoryHC()
    {
      Seed();
    }

    public TicketRepositoryHC(Mock<IList<Ticket>> ticketsMock)
    {
        this.ticketsMock = ticketsMock;
        Seed();
    }

    private void Seed()
    {
      tickets = new List<Ticket>();
      responses = new List<TicketResponse>();

      // Aanmaken eerste ticket met drie responses
      Ticket t1 = new Ticket()
      {
        TicketNumber = tickets.Count + 1,
        AccountId = 1,
        Text = "Ik kan mij niet aanmelden op de webmail",
        DateOpened = new DateTime(2012, 9, 9, 13, 5, 59),
        State = TicketState.Closed,
        Responses = new List<TicketResponse>()
      };

      tickets.Add(t1);

      TicketResponse t1r1 = new TicketResponse()
      {
        Id = responses.Count + 1,
        Ticket = t1,
        Text = "Account is geblokkeerd",
        Date = new DateTime(2012, 9, 9, 13, 24, 48),
        IsClientResponse = false
      };
      t1.Responses.Add(t1r1);
      responses.Add(t1r1);

      TicketResponse t1r2 = new TicketResponse()
      {
        Id = responses.Count + 1,
        Ticket = t1,
        Text = "Account terug in orde en nieuw paswoord ingesteld",
        Date = new DateTime(2012, 9, 9, 13, 29, 11),
        IsClientResponse = false
      };
      t1.Responses.Add(t1r2);
      responses.Add(t1r2);

      TicketResponse t1r3 = new TicketResponse()
      {
        Id = responses.Count + 1,
        Ticket = t1,
        Text = "Aanmelden gelukt en paswoord gewijzigd",
        Date = new DateTime(2012, 9, 10, 7, 22, 36),
        IsClientResponse = true
      };
      t1.Responses.Add(t1r3);
      responses.Add(t1r3);

      t1.State = TicketState.Closed;


      //Aanmaken tweede ticket met één response
      Ticket t2 = new Ticket()
      {
        TicketNumber = tickets.Count + 1,
        AccountId = 1,
        Text = "Geen internetverbinding",
        DateOpened = new DateTime(2012, 11, 5, 9, 45, 13),
        State = TicketState.Open,
        Responses = new List<TicketResponse>()
      };

      tickets.Add(t2);

      TicketResponse t2r1 = new TicketResponse()
      {
        Id = responses.Count + 1,
        Ticket = t2,
        Text = "Controleer of de kabel goed is aangesloten",
        Date = new DateTime(2012, 11, 5, 11, 25, 42),
        IsClientResponse = false
      };
      t2.Responses.Add(t2r1);
      responses.Add(t2r1);

      t2.State = TicketState.Answered;

      //Aanmaken eerste HardwareTicket
      HardwareTicket ht1 = new HardwareTicket()
      {
        TicketNumber = tickets.Count + 1,
        AccountId = 2,
        Text = "Blue screen!",
        DateOpened = new DateTime(2012, 12, 14, 19, 15, 32),
        State = TicketState.Open,
        //Responses = new List<TicketResponse>(),
        DeviceName = "PC-123456"
      };

      tickets.Add(ht1);
    }

    #region 'ITicketRepository' implementatie
    public Ticket CreateTicket(Ticket ticket)
    {
      ticket.TicketNumber = tickets.Count + 1;
      tickets.Add(ticket);

      return ticket; //return van ticket testen, niet ReadTicket gebruiken
    }

    public IEnumerable<Ticket> ReadTickets()
    {
      return tickets;
    }

    public Ticket ReadTicket(int ticketNumber)
    {
      return tickets.Find(t => t.TicketNumber == ticketNumber);
    }

    public void UpdateTicket(Ticket ticket)
    {
      // Do nothing! All data lives in memory, everything references the same objects!!
    }

    public void DeleteTicket(int ticketNumber)
    {
      this.responses.RemoveAll(r => r.Ticket.TicketNumber == ticketNumber);
      this.tickets.Remove(ReadTicket(ticketNumber));
    }

    public IEnumerable<TicketResponse> ReadTicketResponsesOfTicket(int ticketNumber)
    {
      return tickets.Find(t => t.TicketNumber == ticketNumber).Responses;
    }

    public TicketResponse CreateTicketResponse(TicketResponse response)
    {
      response.Id = responses.Count + 1;
      responses.Add(response);
      return response;
    }
    #endregion
  }
}

Now, I want to write the following Unit Test (the name of the Unit Test is "TicketHasToBeReadCorrectly, simply I want to test if the ticket that has been added to the repository can be read correctly:

namespace TicketRepositoryTest
{
    [TestClass]
    public class TicketRepositoryTest
    {
        [TestMethod]
        public void TicketMoetCorrectGelezenWorden()
        {
            //Arrange

            var ticketsMock = new Mock<IList<Ticket>>();

            ITicketRepository ticketRepo = new TicketRepositoryHC(ticketsMock);

            //Act

            Ticket ticket = new Ticket() {
                //TicketNumber = 2,
                AccountId = 1,
                Text = "Ik kan mij niet aanmelden op de webmail",
                DateOpened = new DateTime(2012, 9, 9, 13, 5, 59),
                State = TicketState.Open,
                Responses = new List<TicketResponse>()
            };

            var returnTicket = ticketRepo.CreateTicket(ticket);


            //Assert
            ticketsMock.Verify(l => l.Add(It.IsAny<Ticket>()));
            Assert.ReferenceEquals(ticket, returnTicket);
            Assert.IsTrue(ticket.TicketNumber != default(int));

        }
    }
}

But this test fails with the following message:

Test Name: TicketMoetCorrectGelezenWorden Test FullName: TicketRepositoryTest.TicketRepositoryTest.TicketMoetCorrectGelezenWorden Test Source: .Eg_SupportCenter\TicketRepositoryTest\TicketRepositoryTest.cs : line 19 Test Outcome: Failed Test Duration: 0:00:00,0388466

Result StackTrace: at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable1 setups, IEnumerable1 actualCalls, Expression expression, Times times, Int32 callCount) at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times) at Moq.Mock.Verify[T](Mock1 mock, Expression1 expression, Times times, String failMessage) at Moq.Mock1.Verify(Expression1 expression)
at TicketRepositoryTest.TicketRepositoryTest.TicketMoetCorrectGelezenWorden() in .\Eg_SupportCenter\TicketRepositoryTest\TicketRepositoryTest.cs:line 41 Result Message: Test method TicketRepositoryTest.TicketRepositoryTest.TicketMoetCorrectGelezenWorden threw exception: Moq.MockException: Expected invocation on the mock at least once, but was never performed: l => l.Add(It.IsAny()) No setups configured. No invocations performed.

Could anyone tell me what I'm doing wrong? TicketRepository with Mock:

 public class TicketRepositoryHC : ITicketRepository
  {
    private List<Ticket> tickets;
    private List<TicketResponse> responses;
    private Mock<IList<Ticket>> ticketsMock;

        public TicketRepositoryHC()
    {
      Seed();
    }

        public TicketRepositoryHC(Mock<IList<Ticket>> ticketsMock)
        {
            this.ticketsMock = ticketsMock;
            Seed();
        }
1
Thanks for your first contribution on StackOverflow. Consider reducing the amount of code that you include. There is guidance on creating a minimal complete and verifiable example. Basically keep only the code that creates the error. - M. K. Hunter
You may also learn a lot from the process of simplifying the code down to just what generates the error. - M. K. Hunter

1 Answers

0
votes

Take out all your mock stuff from the repository. This is wrong. Create a mock version of type TicketRepositoryHC and use Moq's Setup() to mock your methods, ReadTicketResponsesOfTicket() etc..