Unable to access variables from another project - c#

I am trying to automate API testing using c# (Restsharp). I have 2 projects in same solution. One project is a console app where I am trying to keep the methods, while the other one is a Unit Test Project where I plan on keeping the test cases.
I am able to access the methods from the BASE project by creating an object of the method, but unable to access the variables within that method to apply assertions. Any idea what am I missing?
(I am new to c#).
Method class in Base project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using RestSharp;
namespace Base
{
public class Methods
{
public void GetMethod(long ID)
{
var client = new RestClient("getUrl");
var request = new RestRequest(Method.GET);
request.AddParameter("userId", ID);
IRestResponse response = client.Execute(request);
HttpStatusCode statusCode = response.StatusCode;
int nStatusCode = (int)statusCode;
}
}
}
UnitTest class in Test project
using System;
using System.Net;
using Base;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RestSharp;
namespace Tests
{
[TestClass]
public class UnitTests
{
[TestMethod]
public void StatusOK()
{
//Arrange, Act, Assert
var methods = new Methods();
methods.GetMethod(2330013)
Assert.IsTrue(nStatusCode.Equals(200));
}
}
}
UnitTest is unable to read nStatusCode variable, as well as response variable.
I have already added dependency between the projects.
Appreciate the help!!

One option to address the problem is to make GetMethod return the status code:
public int GetMethod(long ID)
{
...
int nStatusCode = (int)statusCode;
return nStatusCode;
}
Then the test can examine the return value.
var c = methods.GetMethod(2330013)
Assert.AreEqual(200, c);
PS. I recommend using Assert.AreEqual instead of Assert.IsTrue because in the case the code is not 200 the test failure output will contain the bad value. With IsTrue you will only know that it wasn't 200 but you won't know what it was.

Related

SignalR HubContext Clients is null after running Unit test on it with Mock client proxy

I have the following 2 files, one, which is a HubController class and the other, which is a Unit test class.
HubController.cs:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace SignalR.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class HubController : ControllerBase
{
private readonly IHubContext<HothHub> _hubContext;
public HubController(IHubContext<HothHub> hubContext)
{
_hubContext = hubContext;
}
[HttpPost("{id}")] // POST /api/values/xyz
public async Task PostAsync(string id)
{
Trace.TraceInformation("update Post()");
// Make a call to the client based on the connection ID and call client method
await _hubContext.Clients.Client(id).SendAsync("hubToClientUpdate");
//return Ok();
}
}
}
Tests.cs:
using Xunit;
using Moq;
using System.Dynamic;
using SignalR;
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
using SignalR.Controllers;
using Microsoft.AspNet.SignalR.Hubs;
using System;
namespace TestSignalR
{
public class Tests
{
[Fact]
public async Task HubsAreMockableViaDynamic()
{
bool sendCalled = false;
var mockClients = new Mock<IHubCallerConnectionContext<dynamic>>();
// The IHubCallerConnectionContext interface is the proxy object with, which you invoke methods on the client
dynamic all = new ExpandoObject();
// This is the client proxy object where we define the method, which we will invoke on the client
all.SendAsync = new Action<string>((method) =>
{
sendCalled = true;
});
// Define the function that will be called on the client when HubController calls its PostAsync method
// The test engine will call the PostAsync method in HubController, which in turn calls this method postAsync here
mockClients.Setup(m => m.All).Returns((ExpandoObject)all);
// Setting up the mock client so when the All property is called we return an instance of the Client proxy, which in this case
// is the dynamic object all
var hubContext = new Mock<IHubContext<MyHub>>();
// Created a mock of the IHubContext object required by the HubController class
hubContext.Setup(x => x.Clients).Returns(mockClients.Object as IHubClients);
// Set up the mock of the IHubContext object so that when the Clients property is called, then the instance of the mock client
// object is returned
HubController hubController = new HubController(hubContext.Object);
// Created an instance of the HubController class, which is needed to call the PostAsync function in it
await hubController.PostAsync("id");
Assert.True(sendCalled);
}
}
}
I also have a MyHub.cs file, which derives from the Hub class but this class doesn't contain anything useful for my test.
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SignalR
{
public class MyHub : Hub
{
public string GetConnectionId() => Context.ConnectionId;
}
}
Now the issue I'm having is that when I either run a test on HubsAreMockableViaDynamic() or run a debug on it, it will return me the following error,
This test has come about after following the documentation from Microsoft here https://learn.microsoft.com/en-us/aspnet/signalr/overview/testing-and-debugging/unit-testing-signalr-applications. Now I suspect the problem is with this line here, hubContext.Setup(x => x.Clients).Returns(mockClients.Object as IHubClients); in Tests.cs, which is causing the problem. Without the cast there is the following,
Severity Code Description Project File Line Suppression State
Error CS1503 Argument 1: cannot convert from 'Microsoft.AspNetCore.SignalR.IHubClients' to 'Microsoft.AspNetCore.SignalR.IHubClients' TestSignalR C:\Sourcesafe\2023\Integration\WebhookBot\WebhookBot\TestSignalR\Tests.cs 38 Active
I'm quite new to SignalR and Mock objects so I'm stuck as to why this isn't working after following the documentation from Microsoft. Is there anyone who could shed some light into why this issue is happening and how to resolve it please?
Thanks!

Get JSON data out of Umbraco

I am a frontend developer so forgive my lack of ability to explain my issue.
I am trying to create some pages in an Umbraco project that display data using Vue.js. For this, I am trying to set up a custom API controller that will return the data I want, when called.
A simple example would be that I want to return all blog articles. Below is the code I have currently got:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Web;
using System.Web.Http;
using Umbraco.Web.WebApi;
using Umbraco.Web.PublishedContentModels;
using Newtonsoft.Json;
namespace Controllers.WebAPI.Qwerty
{
[Route("api/[controller]")]
public class PostsApiController : UmbracoApiController
{
[HttpGet]
public string Test()
{
return "qwerty";
}
}
}
I've read numerous articles and just can't seem to grasp what I need to do to query Umbraco for the data I want back?
I've tried adding
var content = Umbraco.TypedContent(1122);
And then returning that but I get errors stating:
(local variable) Umbraco.Core.Models.IPublishedContent content
Cannot implicitly convert type 'Umbraco.Core.Models.IPublishedContent' to 'string'
I have then tried serialising the var content but I get stuck with:
Self referencing loop detected for property 'FooterCtalink' with type
'Umbraco.Web.PublishedContentModels.Blog'. Path
'ContentSet[0].FeaturedProducts[0].Features[0].ContentSet[0]'.
Any help would be fantastic!
EDIT:
I have no edited the controller to be like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Web;
using Umbraco.Web.WebApi;
using Umbraco.Web.PublishedContentModels;
using Newtonsoft.Json;
using System.Web.Mvc;
using DTOs.PostDTO;
namespace Controllers.WebAPI.Qwerty
{
[Route("api/[controller]")]
public class PostsApiController : UmbracoApiController
{
[HttpGet]
public PostDTO Test()
{
// 1. Get content from umbraco
var content = Umbraco.TypedContent(1122);
// 2. Create instance of your own DTO
var myDTO = new PostDTO();
// 3. Pupulate your DTO
myDTO.Url = content.Url;
// 4. return it
return myDTO;
}
}
}
And created a DTO like so:
namespace DTOs.PostDTO
{
public class PostDTO
{
public string Url { get; set; }
}
}
However, when console logging my data after the ajax request, I only only getting 1122.
The issue is that you can't return a .NET Object in JSON that has the circular dependency.
To solve your problem, you can simply follow the below steps:
Create your own DTO & add required properties in that.
Fetch content from Umbraco API in C# & populate your custom DTO object.
Return that DTO from JsonResult.
Your code will look like below:
[Route("api/[controller]")]
public class PostsApiController : UmbracoApiController
{
[HttpGet]
public MyDTO Test()
{
// 1. Get content from umbraco
var content = Umbraco.TypedContent(1122);
// 2. Create instance of your own DTO
var myDTO = new MyDTO();
// 3. Pupulate your DTO
myDTO.SomeProperty = content.SomeProperty;
// 4. return it
return myDTO;
}
}
You are on the right track.
I think you need to return ActionResult instead of string.
Something like:
[HttpGet]
public ActionResult Test()
{
var content = Umbraco.TypedContent(1122);
return new JsonResult(content);
}
This should return the umbraco object as Json.

Unity, Moq, and NUnit - Controller Constructor with Parameters Not Recognized in Tests

I am very new to unit testing, so I apologize if this is not a very good question.
I have a main web project, and an accompanying NUnit tests library. I am using Unity to inject interfaces into my controller within the main project. For example:
public class EquipmentController : Controller
{
private readonly ILocationRepository locationContext = null;
private readonly IRepository<EquipmentCategory> categoryContext = null;
private readonly IEquipmentRepository equipmentContext = null;
private readonly IRecordRepository recordContext = null;
public EquipmentController(ILocationRepository locationRepo, IRepository<EquipmentCategory> categoryRepo, IEquipmentRepository equipmentRepo, IRecordRepository recordRepo)
{
this.locationContext = locationRepo;
this.categoryContext = categoryRepo;
this.equipmentContext = equipmentRepo;
this.recordContext = recordRepo;
}
The web application itself actually works as expected. However, I am encountering issues while trying to write test cases. For example, in test library, I have the following:
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity.Mvc;
using Microsoft.Practices.Unity.ObjectBuilder;
using Microsoft.Practices.Unity.StaticFactory;
using Moq;
using ITEquipmentDatabase;
using ITEquipmentDatabase.Models;
using ITEquipmentDatabase.Controllers;
namespace ITEquipmentDatabase.Tests
{
[TestFixture]
public class EquipmentController
{
[Test]
public void TestMethod()
{
var equipRepo = new Mock<IEquipmentRepository>();
var categoryRepo = new Mock<IRepository<EquipmentCategory>>();
var locationRepo = new Mock<ILocationRepository>();
var recordRepo = new Mock<IRecordRepository>();
EquipmentController controller = new EquipmentController(locationRepo.Object, categoryRepo.Object, equipRepo.Object, recordRepo.Object);
}
}
}
However, I am receiving the following error:
Error 1 'ITEquipmentDatabase.Tests.EquipmentController' does not contain a constructor that takes 4 arguments C:\Users\Khandokar\Documents\Visual Studio 2013\Projects\IT Equipment Log\ITEquipmentDatabase.Tests\EquipmentController.cs 27 46 ITEquipmentDatabase.Tests
I have Unity referenced in my tests project and even added Bootstrapper.cs (not sure if it was necessary, but I was trying to resolve the above issue). I am quite sure I am doing something very wrong, but I am just starting to venture into unit testing and am having a bit of a difficult time.
Thanks for any advice.
Your test class is named EquipmentController and so is your class under test.
Rename your test class to EquipmentControllerTests or some such.
(The error message was the clue; note that it refers to Tests.EquipmentController).

System.Web.Http assembly not allways visible in same c# project

I have a C# project where in my controller class the System.Web.Http library can be referenced but in the another class it cannot. The reference has been added to the overall project and both classes have all the necessary using directives.
The Request method of System.Web.Http cannot be resolved in some instances?
Here are code snippets of the two classes:
Controllers/FormsController.cs
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.Description;
using FormsImport.Models;
namespace FormsImport.Controllers
{
public class TCSTasksController : ApiController
{
[Route("api/TCSUploadFile")]
[AllowAnonymous]
public async Task<HttpResponseMessage> UploadCSVFile()
{
try
{
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created); // <-- the name Request does exists
.
.
.
}
CSVmanager.cs
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http; //<-- Compiler claims this directive is unneccesary
using System.Web.Http.Description;
using FormsImport.Models;
namespace FormsImport
{
public class CSVmgr
{
public async Task<HttpResponseMessage> UploadCSVFile()
{
try
{
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created); // <-- the name Request Does not exist in the current context
.
.
.
}
I think you should agree with your compiler/IDE (Visual Studio?) in this case - it's simply pointing out that the referenced assembly is not in use in this class.
Should you decide to use any functionality from this assembly, the warning in question will go away.
EDIT based on comment: If the functionality you need is part of a protected interface of another class, such as ApiController, you MUST extend that class to access such functionality in your own class. If such extension subsequently uses methods in the assembly you referenced (and for which the compiler shows an unnecessary using directive), the compiler warning regarding the using directive will likewise resolve.
in your api controller, Request is a HttpRequestMessage type, and the CreateResponse is the extension method of HttpRequestMessage. why not create a HttpResponseMessage new instance in your CSVmgr class. like:
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
codran 17 explained it the best.
My new class is not derived from the APIController Class and the Request method of that class is not a static function that I can call like System.IO.Path() for instance. So I must use another static function from a class that returns the same results or pass a reference to the APIController to my new class.
Like so:
public async Task<HttpResponseMessage> UploadCSVFile(ApiController controller)
{
Dictionary<string, object> dict = new Dictionary<string, object>();
try
{
var httpRequest = HttpContext.Current.Request;
foreach (string file in httpRequest.Files)
{
HttpResponseMessage response = controller.Request.CreateResponse(HttpStatusCode.Created);

ASP.NET Syntax and conventions

I am reading Designing Evolvable Web APIs with ASP.NET. In one of the exercises, the book has me edit a Controller using Visual Studio. This is being done in ASP.NET using C#. The template I used was the standard ASP.NET web application API.
I have edited the controller to the way the book shows (although it does not seem to give very specific directions). Here is what my controller looks like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using WebApplication4.Models;
using WebApplication4.Providers;
using WebApplication4.Results;
namespace WebApplication4.Controllers
{
public class GreetingController : ApiController
{
public string GetGreeting() {
return "Hello World!";
}
}
public static List<Greeting> _greetings = new List<Greeting>();
public HttpResponseMessage PostGreeting(Greeting greeting)
{
_greetings.Add(greeting);
var greetingLocation = new Uri(this.Request.RequestUri, "greeting/" + greeting.Name);
var response = this.Request.CreateResponse(HttpStatusCodeResult.Created);
response.Headers.Location = greetingLocation;
return response;
}
}
I get errors on:
_greetings: A namespace cannot directly contain members such as fields or methods
PostGreeting: A namespace cannot directly contain members such as fields or methods,
_greetings : does not exist in the current context
Request : <invalid-global-code> does not contain a definition for 'request',
Created: HttpStatusCodeREsult does not contain a definition for 'Created'
As the error is trying to tell you, your fields and methods must be inside the class.
Check your braces.
Your _greetings field needs to be part of the class, as well as the PostGreeting method, it seems you just closed "}" of the class a bit early.
MOve the "}" before the _greetings field to the end of the file, like:
namespace WebApplication4.Controllers
{
public class GreetingController : ApiController
{
public string GetGreeting() {
return "Hello World!";
}
public static List<Greeting> _greetings = new List<Greeting>();
public HttpResponseMessage PostGreeting(Greeting greeting)
{
_greetings.Add(greeting);
var greetingLocation = new Uri(this.Request.RequestUri, "greeting/" + greeting.Name);
var response = this.Request.CreateResponse(HttpStatusCodeResult.Created);
response.Headers.Location = greetingLocation;
return response;
}
}
}

Categories

Resources