Sorry If i confuse anyone with the question, I am trying hard to make the scenario clear.
Am writing Test Cases for a method that invoke HttpClient Methods.So, I ended up writing following Test Method.
[TestMethod]
public async Task CallComplexRefTypeParamAPI_Get_GetResponseWithParamatersNameValueAppended()
{
#region Arrange
//var resourceURL = #"http://localhost:32662/api/user/ComplexReferenceTypeParamStringResponse";
var resourceURL = #"/api/user/ComplexReferenceTypeParamStringResponse";
var restHelper = new RestHelper(_BaseAddress);
string ParameterKey1 = "VariableStr";
string ParameterValueStr = "Jia";
string ParameterKey2 = "VariableInt";
int ParameterValueInt = 1;
string ParameterKey3 = "VariableBool";
bool ParameterValueBool = true;
string ParameterKey4 = "VariableDateTime";
DateTime ParameterValueDateTime = DateTime.Now;
ComplexRefType ParameterComplexRefType = new ComplexRefType()
{
VariableBool = ParameterValueBool,
VariableDateTime = ParameterValueDateTime,
VariableInt = ParameterValueInt,
VariableStr = ParameterValueStr
};
string result;
#endregion
#region Act
using (WebApp.Start<WebApiStartup>(_BaseAddress))
{
restHelper.AddURLParameters("VariableComplexRef", ParameterComplexRefType);
restHelper.AddURLParameters("DummyStr", "DummyStr");
result = await restHelper.ExecuteAsync<string>(HttpMethod.Get, resourceURL);
}
#endregion
#region Assert
Assert.AreEqual<string>(string.Format("{0}={1}&{2}={3}&{4}={5}&{6}={7}",
ParameterKey1, ParameterValueStr,
ParameterKey2, ParameterValueInt,
ParameterKey3, ParameterValueBool,
ParameterKey4, ParameterValueDateTime), result);
#endregion
}
On other side, I have my Test Controller with following 2 methods.
public string GetMultipleTypeParamStringResponse(string VariableStr, int VariableInt, DateTime VariableDateTime)
{
return string.Format("VariableStr={0}&VariableInt={1}&VariableDateTime={2}", VariableStr, VariableInt, VariableDateTime);
}
public string GetComplexReferenceTypeParamStringResponse([FromUri]ComplexRefType VariableComplexRef, string DummyStr)
{
return string.Format("VariableStr={0}&VariableInt={1}&VariableBool={2}&VariableDateTime={3}",
VariableComplexRef.VariableStr,
VariableComplexRef.VariableInt,
VariableComplexRef.VariableBool,
VariableComplexRef.VariableDateTime);
}
I have the same Controller replicated in an Web API application. If run the test method, pointing to the Self-Hosted API, the application hits "GetMultipleTypeParamStringResponse" instead of "GetComplexReferenceTypeParamStringResponse". However, if I run it against the Web API, it hits the rightful "GetComplexReferenceTypeParamStringResponse" method.
Could someone please help me understand why this behavior ? On both cases, the Query String generated looks to be similar.
Self Hosted
http://localhost:8888/api/user/ComplexReferenceTypeParamStringResponse?VariableStr=Jia&VariableInt=1&VariableBool=True&VariableDateTime=1%2F5%2F2017 3:49:10 PM&DummyStr=DummyStr
Web API
http://localhost:32662/api/user/ComplexReferenceTypeParamStringResponse?VariableStr=Jia&VariableInt=1&VariableBool=True&VariableDateTime=1%2F5%2F2017 3:50:58 PM&DummyStr=DummyStr
Change the routetemplate in your route configuration to
routeTemplate: "api/{controller}/{action}/{id}"
Mark the methods with explicit Route attribute and HttpGet verb like below
[HttpGet]
[Route("api/user/ComplexReferenceTypeParamStringResponse")]
Related
I'm making some dApp using Unity & Nethereum.
I deployed one contract to the Ropsten Test Net using Remix. And I had abi & bytecode of that, so I made Definition & Service C# code using solodity package of VS Code.
I wanted to mint new NFT, and below is the code that I tried.
string url = "my infura - ropsten url";
string privateKey = "private Key of my MetaMask account";
string userAddress = "public address of my MetaMask account";
string contractAddress = "address of deployed contract";
var account = new Account(privateKey);
var web3 = new Web3(account, url);
var service = new MyNFTService(web3, contractAddress);
var mintReceipt = await service.MintRequestAndWaitForReceiptAsync(userAddress, "address of metadata");
But I can't get receipt even after a long time... Why is this happening? I can't get any answer about that, and I just have to wait.
I have tried everything that I can do, like SendTransactionAndWaitForReceiptAsnyc(), SignAndSendTransaction(), and so on.
The version of Nethereum is 4.1.1, and the version of Unity is 2019.4.21f1.
Below is the part of definition code. (mint)
public partial class MintFunction : MintFunctionBase { }
[Function("mint", "uint256")]
public class MintFunctionBase : FunctionMessage
{
[Parameter("address", "user", 1)]
public virtual string User { get; set; }
[Parameter("string", "tokenURI", 2)]
public virtual string TokenURI { get; set; }
}
And below is the part of service code. (mint)
public Task<string> MintRequestAsync(MintFunction mintFunction)
{
return ContractHandler.SendRequestAsync(mintFunction);
}
public Task<TransactionReceipt> MintRequestAndWaitForReceiptAsync(MintFunction mintFunction, CancellationTokenSource cancellationToken = null)
{
return ContractHandler.SendRequestAndWaitForReceiptAsync(mintFunction, cancellationToken);
}
public Task<string> MintRequestAsync(string user, string tokenURI)
{
var mintFunction = new MintFunction();
mintFunction.User = user;
mintFunction.TokenURI = tokenURI;
return ContractHandler.SendRequestAsync(mintFunction);
}
public Task<TransactionReceipt> MintRequestAndWaitForReceiptAsync(string user, string tokenURI, CancellationTokenSource cancellationToken = null)
{
var mintFunction = new MintFunction();
mintFunction.User = user;
mintFunction.TokenURI = tokenURI;
return ContractHandler.SendRequestAndWaitForReceiptAsync(mintFunction, cancellationToken);
}
I am struggle with this problem for five days... Please help me..
I solved it today! (But I didn't use my service code)
In my opinion, the reason why the transaction didn't work is that the miner can't mine my transaction. (Exactly, they can mine, but they didn't because mining other transaction will give them more money.)
In the document of Netherum, they speak nethereum can set the gas price as the average, but I though it didn't work. After I added a code to estimate and set the gas price, SendRequestAndWaitForReceiptAsync() worked very well. (And I could receive transaction hash.)
Below is the code that I used to solve this problem.
var mintHandler = web3.Eth.GetContractTransactionHandler<MintFunction>();
var mint = new MintFunction()
{
User = userAddress,
TokenURI = "Token URI"
};
mint.GasPrice = Web3.Convert.ToWei(25, UnitConversion.EthUnit.Gwei);
var estimate = await mintHandler.EstimateGasAsync(contractAddress, mint);
mint.Gas = estimate.Value;
var mintReceipt = await mintHandler.SendRequestAndWaitForReceiptAsync(contractAddress, mint);
Debug.Log(mintReceipt.TransactionHash);
I need to do Moq test for the below original method
public virtual User GetBOUser(string domainName, string userName, string password, Login model)
{
try
{
if (Sitecore.Security.Accounts.User.Exists(domainName + #"\" + userName))
{
User user = Sitecore.Security.Accounts.User.FromName(domainName + #"\" + userName, true);
return user;
}
}
catch (Exception ex)
{
Log.Error("GetBOUser Error - " + ex.ToString(), this);
}
return null;
}
The sample unit test method I have created is below
[TestMethod]
public void LoginApiTest()
{
User use = null;
var mockapi = new Mock<ApiController>();
mockapi.Setup(x => x.GetBOUser("", "", "", new Login())).Returns(use);
var dataObject = mockapi.Object;
Assert.AreEqual<User>(use, dataObject.GetBOUser("", "", "", new Login()));
}
Here I am able to check only for null in the return type of test method, But how to return a actual user object ?
Before I address your question, I need to point out that your sample test is not actually testing anything. You are mocking your system under test, telling it to return null and then asserting that it returned null. This will not execute your production code.
You should be creating a normal instance of your ApiController. However, that highlights another issue in that your method has a dependency on Sitecore's static security API. If you want your code to be testable, you will need to create an interface and wrapper class for that API and make your controller accept an instance of your interface in its constructor so that you can provide a mock instance for your test but a real instance in production.
Your wrapper class should only call the static API and should contain no logic. That way you don't really need to test it. When you set up the mock instance of your interface you can create a mock IPrincipal and pass it to User.FromPrincipal to prevent it from actually trying to lookup the user in the database. If you were to name your interface IUserService, your test would end up looking something like this:
[TestMethod]
public void GetBOUser_WithExistingUser_ReturnsUser()
{
// Arrange
var name = "Joe";
var domain = "extranet";
var fullName = domain + #"\" + name;
var principal = new Mock<IPrincipal>();
principal.Setup(p => p.Identity.Name).Returns(fullName);
var joeUser = User.FromPrincipal(principal);
var userService = new Mock<IUserService>();
userService.Setup(u => u.Exists(fullName)).Returns(true);
userService.Setup(u => u.FromName(fullName)).Returns(joeUser.Object);
var controller = new ApiController(userService.Object);
// Act
var result = controller.GetBOUser("extranet", "Joe", "password", new Login());
// Assert
Assert.AreEqual(fullName, result.Name);
}
One other thing... Your GetBOUser method accepts a password, but does not validate it before returning a user. That is very misleading to consumers of your API. If you accept a password you should make sure it is correct before returning the requested user object.
Can any one suggest another way to integrate NodeJs in .Net MVC application? I am now using the following code:
public class Startup
{
public async Task<object> Invoke(dynamic input)
{
DepartmentRep person = new DepartmentRep(new MvcAppUsingEdgeJSMongoDbContext());
var department= person.GetAllDepartments();
//var department = "hello";
return department;
}
}
public class DepartmentController : Controller
{
DepartmentRepository departmentRepository = new DepartmentRepository(new MvcAppUsingEdgeJSMongoDbContext());
string connectionString = ConfigurationManager.AppSettings["connectionString"].ToString();
public ViewResult Index()
{
// var clrMethod = Edge.Func("DepartmentRep.cs");
var getData = Edge.Func("./DepartmentRep.dll");
// return View(clrMethod);
return View(departmentRepository.GetAllDepartments());
}
}
It seems to me, you may have a misunderstanding of the EdgeJs use case.
Your Startup/Invoke class/Signature is meant to be called from Node(JavaScript),
And from the code you are showing it looks like you are loading .Net from .Net
Also , as the Invoke signature suggest, It should be asynchronous.
If you want to use node from .Net side. You should check the project documentation from
scripting-nodejs-from-clr downwards.
var func = Edge.Func(#"
return function (data, callback) {
callback(null, 'Node.js welcomes ' + data);
}
");
As you can see there the wrapped code is Javascript, this time running in .Net more specifically running in Node.
The perfect use case IMMO is the Socket-Server, that is, something Node does better than .Net (IMMO again)
Which is in perfect contrast with the .Net Ado Sql Server access from NodeJs, a .Net Specialization from NodeJs context
I have a custom action filter that will log user actions automatically using a [Log] attribute in my controllers. I've used this same setup in multiple applications so I know it works, but this time it's failing and I can't figure out why.
public override void OnResultExecuted(ResultExecutedContext thisContext)
{
LogTrace(thisContext.RouteData);
}
public void LogTrace(RouteData routeData)
{
MyContext db = new MyContext();
TimeSpan Duration = (DateTime.Now - StartTime);
string Controller = ReadableController((string)routeData.Values["controller"]);
string Action = (string)routeData.Values["action"];
long? ID = (long?)routeData.Values["id"];
LogFile log = new LogFile();
log.UserID = User.ID;
log.Controller = Controller;
log.Action = Action;
log.ItemID = ID;
log.Timestamp = DateTime.Now;
log.Duration = Duration;
db.LogFiles.Add(log);
db.SaveChanges();
}
I'm getting 'specified cast is invalid' on LogFile log = new LogFile().
It's not that, the error is one line up, here:
long? ID = (long?)routeData.Values["id"];
Check your route data. id is not a long. It must be a string or even something else.
If it is a numeric type which you store as a string then you have other options to convert it, such as Convert.ToInt64.
I want to be able to mock the object that is returned by SPServer.Local but I can't seem to do it in typemock. At the moment when I debug, I see that SPServer.Local returns a null object of type SPServer. Shouldn't typemock be swapping out this instance with my fake instance? Is there something I'm doing wrong? The code runs fine on the sharepoint server.
[TestInitialize]
public void Setup()
{
fakeSite = Isolate.Fake.Instance<SPSite>(Members.ReturnRecursiveFakes);
Isolate.Swap.NextInstance<SPSite>().With(fakeSite);
fakeServer = Isolate.Fake.Instance<SPServer>(Members.ReturnRecursiveFakes);
Isolate.Swap.NextInstance<SPServer>().With(fakeServer);
sharePointStorageRepository = new SharePointStorageRepository();
}
[TestMethod]
[Isolated]
public void CreateHRFolderMethodCreatesHRFolder()
{
// arrange
// some arrange logic here
// act
var actual = sharePointStorageRepository.Create();
// assert
Assert.AreEqual(expected, actual);
}
This is the bit of code that is being run:
internal static Guid GetSiteGuid(string serverRelativeUrl, string webApplicationName)
{
Guid? guid = null;
SPServer myServer = SPServer.Local;
foreach (var serviceInstance in myServer.ServiceInstances.Where(si => si.Service is SPWebService)){
var service = (SPWebService) serviceInstance.Service;
var webapp = service.WebApplications.SingleOrDefault(wa => wa.DisplayName == webApplicationName);
if (webapp != null){
var site = webapp.Sites.SingleOrDefault(wa => wa.ServerRelativeUrl == serverRelativeUrl);
if (site != null) guid = site.ID;
}
}
if (!guid.HasValue){
throw new FileNotFoundException(
String.Format(
"Cannot find Site Collection with WebApplication \"{1}\" and ServerRelativeUrl \"{2}\" running on \"{0}\"",
myServer.Address, webApplicationName, serverRelativeUrl));
}
return guid.Value;
}
Thanks all!
I don't work in SharePoint, but something I noticed: You're not actually mocking the return of SPServer.Local anywhere. I think that's the missing step. I'm also not entirely sure you need to SwapNextInstance since I don't see anywhere that is actually creating an SPServer object.
That would change your test code to:
[TestInitialize]
public void Setup()
{
// I don't see where you're using SPSite, so I assume it's in code
// not being shown; otherwise you can remove this.
fakeSite = Isolate.Fake.Instance<SPSite>(Members.ReturnRecursiveFakes);
Isolate.Swap.NextInstance<SPSite>().With(fakeSite);
fakeServer = Isolate.Fake.Instance<SPServer>(Members.ReturnRecursiveFakes);
// INSTEAD OF THIS: Isolate.Swap.NextInstance<SPServer>().With(fakeServer);
// DO THIS:
Isolate.WhenCalled(() => SPServer.Local).WillReturn(fakeServer);
sharePointStorageRepository = new SharePointStorageRepository();
}
That WhenCalled method will mean that any time anyone asks for SPServer.Local, it'll return your fake instance.
Note that I see in the code being tested that you get the ServerInstances property. I don't see any specific return values getting set up, so I assume you're controlling the rest of the stuff in the omitted "arrange" logic.