Test Driven Development – MOQ, SignalR

Tags

, , ,

xUnit.net is a free, open source, community-focused unit testing tool for the .NET Framework built to support Test Driven Development.

xUnit.net[runners: Visual Studio] include supports for running xUnit.net test from within visual studio.

Moq is a popular and friendly mocking framework for .NET.

When forking out my test cases || Facts depending on whose in charge, I tend to limit myself to either MSTest or xUnit as my framework of choice depending on my mood at the time.

ranting, ranting……

Why do I like creating my test first before tackling the actual pieces of code?

well, once I write a solid test covering all the scenarios that are important/of use at the moment, I can rest assure that whatever piece of code I write to make that test green is fully functional as far as the application is concerned even if not fully secure(wee, another test to be passed for that one too).

My test naming convention learned from others:

MethodName_StateUnderTest_ExpectedBehavior

–Bravo, bravo, claps ….whistling….., what a well structure bedroom dev….bravo….

thank you

–whistling, bravo, ….

thank you

–yea right, please get back to the title of the article and tell us something simple we can learn from and possibly enjoy.

add the following below to AssemblyInfo.cs file to allow the test class to access internal methods (suitable when trying to avoid dependency injection at times) and classes of the assembly under test suitable for testing scenario

[assembly: InternalsVisibleTo(“ConsolerParserTest”)]

[ConditionalAttribute(“Debug”)] may also be of use in testing scenarios.

A few days ago, writing my test cases for a signalR project, I got the following exception : System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: hb => hb.Groups

hb here represents my actual Hub concrete implementation and its Groups member property is of type IGroupManager.  the exception clearly states what is wrong here.  The property can not be supplanted during the HubMock setup.

Work around:

directly set the property on the mock object instance as follow:

HubMock.Object.Groups  =  groupMock.Object;

luckily that property had a setter otherwise there would not have been any workaround. That being said, here is a simple test case for SignalR Groups

[TestMethod]
        [TestCategory(ChatHubTest.Testcategory)]
        public void StartPrivateChat_ListOfUserNames_GroupId_Created_Nd_MemberUsers_Notified() {
            //Arrange
            ChatHub.LoggedInUsers.AddOrUpdate(Guid.NewGuid().ToString(), new LoggedInChatUser() { Name = "First", SessionId = Guid.NewGuid().ToString() }, ((string ke, LoggedInChatUser usr) => { return usr; }));
            ChatHub.LoggedInUsers.AddOrUpdate(Guid.NewGuid().ToString(), new LoggedInChatUser() { Name = "SecondUser", SessionId = Guid.NewGuid().ToString() }, ((string ke, LoggedInChatUser usr) => { return usr; }));
            ChatHub.LoggedInUsers.AddOrUpdate(Guid.NewGuid().ToString(), new LoggedInChatUser() { Name = "Third_user", SessionId = Guid.NewGuid().ToString() }, ((string ke, LoggedInChatUser usr) => { return usr; }));

            var currentUserConId = Guid.NewGuid().ToString();
            var currentUserSessionId = Guid.NewGuid().ToString();
            var currentUserName = "Musmus";

            Message NotificationMessageToBeSentToGroupMembers = null;

            ChatHub.LoggedInUsers.AddOrUpdate(currentUserConId, new LoggedInChatUser() { Name = currentUserName, SessionId = currentUserSessionId }, ((string ke, LoggedInChatUser usr) => { return usr; }));

                //Construct Group id comprised of Musmus, Third_user and First
            var listOfNames = new[]{"Musmus", "Third_user", "First"};
           /* var names_conId = from kvl in ChatHub.LoggedInUsers
                              where listOfNames.Contains(  kvl.Value.Name)
                              select new {
                                  Name = kvl.Value.Name,
                                  ConnectionId = kvl.Key
                              }
                              into nameConIds
                              orderby nameConIds.Name
                              select nameConIds
                              ;

            var groupName = String.Join("_", (from name in names_conId
                                              select name.Name)
                            .ToArray<String>());*/

            string[] connectionIds = null;

            var groupName = ChatHub.ConstructGroupId(listOfNames, out connectionIds);

                            
            var groupTrackingDictionary = new System.Collections.Generic.Dictionary<string, List<String>>();
            groupTrackingDictionary[groupName] = new List<string>();

            var requestMock = Mock.Of<IRequest>(req => req.User.Identity.Name == currentUserName);
            //
            var groupMock = new Mock<IGroupManager>();
            groupMock.Setup(grp => grp.Add(It.Is<string>(it => it.Equals(groupName)), It.IsAny<string>())).Returns<string, string>((frst, secnd) =>   
                Task.Run(() => {
                    groupTrackingDictionary[frst].Add(secnd); return true;
                })
            );

            var hubMock = new Mock<ChatHub>();
            //.SetupProperty<IGroupManager>(hb => hb.Groups, groupMock.Object); //.Returns(groupMock.Object); /* replace setup with SetupProperty ****/
            var hub = hubMock.Object;
            hub.Groups = groupMock.Object;

            hub.Context = new HubCallerContext(requestMock, currentUserConId);

            dynamic group = new ExpandoObject();
            group.SendPrivateMessage = new Action<Message>( msg => 
                NotificationMessageToBeSentToGroupMembers = msg 
                );

            var clientsMock = new Mock<IHubCallerConnectionContext<dynamic>>();
            clientsMock.Setup(clients => 
                clients.Group(groupName)
                ).Returns((ExpandoObject)group);

            hub.Clients = clientsMock.Object;

            var paramlist = listOfNames.Skip(1).ToArray();

            //Act
            hub.StartPrivateChat(paramlist).GetAwaiter().GetResult();

            //Assert
            // group add has been called for the proper groupname
            //Assert.IsNotNull(groupTrackingDictionary[groupName]);
            Assert.IsTrue(groupTrackingDictionary[groupName].Count() > 2);
            Assert.IsNotNull(NotificationMessageToBeSentToGroupMembers);
            Assert.AreEqual(NotificationMessageToBeSentToGroupMembers.MessageType, MessageTypes.Notification);
        
        }
Follow

Get every new post delivered to your Inbox.