Rhino Mock Expect - c#

Why is the response below always null in my test?
SSO.cs
public class SSO : ISSO
{
const string SSO_URL = "http://localhost";
const string SSO_PROFILE_URL = "http://localhost";
public AuthenticateResponse Authenticate(string userName, string password)
{
return GetResponse(SSO_URL);
}
public void GetProfile(string key)
{
throw new NotImplementedException();
}
public virtual AuthenticateResponse GetResponse(string url)
{
return new AuthenticateResponse();
}
}
public class AuthenticateResponse
{
public bool Expired { get; set; }
}
SSOTest.cs
[TestMethod()]
public void Authenticate_Expired_ReturnTrue()
{
var target = MockRepository.GenerateStub<SSO>();
AuthenticateResponse authResponse = new AuthenticateResponse() { Expired = true };
target.Expect(t => t.GetResponse("")).Return(authResponse);
target.Replay();
var response = target.Authenticate("mflynn", "password");
Assert.IsTrue(response.Expired);
}

Your expectation is not correct. You defined that you expect an empty string as parameter on GetResponse, but you pass in the value SSO_URL. So the expectation is not meet and null is returned instead.
You have two options to correct this
One way is to set IgnoreArguments() on the expectation
target.Expect(t => t.GetResponse("")).IgnoreArguments().Return(authResponse);
and the other way is to pass in your SSO_URL as parameter to the GetResponse method like this
target.Expect(t => t.GetResponse("http://localhost")).Return(authResponse);

Related

RestSharp is not serializing entity/object

I'm trying to Post a request using Restsharp Client (version 108.0.3), however I'm getting an error of "Bad Request: Some of mandatory fields are missing". I know the reason the error message is showing is due to the values not being passed / sent with the request. I have tried sending in the values multiple ways, however with only one way being successful (but, this way won't work as I need to do some logic before passing the entity).
For now, I'm trying to send in only 2 values:
[DataContract]
public class UserModel : IBdeoModel
{
[Required]
//[property: JsonPropertyName("name")]
[DataMember(Name = "email")]
public string ClientEmail { get; set; }
[Required]
//[property: JsonPropertyName("password")]
[DataMember(Name = "password")]
public string ClientSecrent { get; set; }
[IgnoreDataMember]
public bool IsNameValue => true;
}
When the code is run, the folling code will be the first step to "setup" some data. A transport model is created to do some logic for data conversion depending on type (e.g. string, int, datetime) - for this step it is primarily to get the password in the required format.
public class BdeoLoginAPI : ApiRoutable, IBdeoLoginApi
{
private readonly IClient _client;
public override string MidRoute => "/prod/v2/login";
public BdeoLoginAPI(IClient client)
{
_client = client;
}
/// <summary>
/// Authenticates the request to Bdeo
/// </summary>
/// <param cref="UserModel">User Auth Model</param>
/// <returns>The result set of properties created in hubspot.</returns>
public UserTokenModel<LoginAuthDetails> AuthenticateBdeo(UserModel entity)
{
string path = GetRoute<UserModel>();
BdeoTransportObject<UserModel> transportModel = new BdeoTransportObject<UserModel>(entity);
//return _client.Execute<UserTokenModel<LoginAuthDetails>, UserModel>(path, entity, Method.Post);
return _client.Execute<UserTokenModel<LoginAuthDetails>, BdeoTransportObject<UserModel>>(path, transportModel, Method.Post);
}
}
The transport model that is being called:
[DataContract]
public class BdeoTransportObject<T> : BdeoTransportModel<T>
{
public BdeoTransportObject() { }
public BdeoTransportObject(T model)
{
ToPropertyTransportModel(model);
}
}
[DataContract]
public abstract class BdeoTransportModel<T>
{
private Dictionary<string, object> Properties { get; set; }
internal void ToPropertyTransportModel(T model)
{
var propertiesToAdd = new Dictionary<string, object>();
PropertyInfo[] modelProperties = model.GetType().GetProperties();
foreach (PropertyInfo modelProp in modelProperties)
{
var memberAttrib = modelProp.GetCustomAttribute(typeof(DataMemberAttribute)) as DataMemberAttribute;
object modelValue = modelProp.GetValue(model);
if (modelValue == null || memberAttrib == null || modelValue.ToString() == string.Empty)
{
continue;
}
//some other logic
propertiesToAdd.Add(memberAttrib.Name, modelValue);
}
Properties = propertiesToAdd;
}
}
Then finally doing the actual RestRequest call.
public T Execute<T, K>(string absoluteUriPath, K entity, Method method = Method.Get) where T : new()
=> SendReceiveRequest<T, K>(absoluteUriPath, method, entity);
private RestRequest ConfigureRequestAuthentication(string path, Method method)
{
string fullPath = $"{BasePath.TrimEnd('/')}/{path.Trim('/')}";
RestRequest request = new RestRequest(fullPath, method);
request.RequestFormat = DataFormat.Json;
return request;
}
private T SendReceiveRequest<T, K>(string path, Method method, K entity) where T : new()
{
RestRequest request = ConfigureRequestAuthentication(path, method);
if (!entity.Equals(default(K)))
{
//string json = System.Text.Json.JsonSerializer.Serialize(entity);
//string json = JsonConvert.SerializeObject(entity);
//request.AddJsonBody(entity);
//string content = JsonConvert.SerializeObject(entity, Formatting.Indented);
request.AddBody(entity);
//request.AddParameter("text/json", entity, ParameterType.RequestBody);
}
var response = _client.Execute<T>(request);
if (!response.IsSuccessful)
{
throw new InvalidOperationException("Failed with " + response.StatusCode.ToString() + ". Error Message: " + response.ErrorMessage);
}
return response.Data;
}
When sending the entity through, the data is definately present, however it seems it is not serializing as it should and throwing the error of BadRequest - mandatory fields are missing.
However, when I take out the middle step for the transport model, it works fine. Making the necessarily alterations to get it to work looks like this:
[DataContract]
public class UserModel : IBdeoModel
{
[Required]
public string email { get; set; }
[Required]
public string password { get; set; }
[IgnoreDataMember]
public bool IsNameValue => true;
}
public UserTokenModel<LoginAuthDetails> AuthenticateBdeo(UserModel entity)
{
string path = GetRoute<UserModel>();
BdeoTransportObject<UserModel> transportModel = new BdeoTransportObject<UserModel>(entity);
return _client.Execute<UserTokenModel<LoginAuthDetails>, UserModel>(path, entity, Method.Post);
// return _client.Execute<UserTokenModel<LoginAuthDetails>, BdeoTransportObject<UserModel>>(path, transportModel, Method.Post);
}
It seems that adding these properties to a dictionary type in the transportmodel is causing the issue when Restharp attempts to serialize it, however I can't seem to see what is wrong to get it to work.

How can I return especific value of a static method in my the method that I am testing?

Here is the method that I am going to test and I want IsPhoneNomValid() would return false so then I would be able to assert my expectations:
public async Task<UserResponseDto> RegisterUser(RegistrationRequestDto register, CancellationToken cancelationToken)
{
// I want the IsPhoneNomValid() method, Would return "FALSE"
var isPhoneNumberValid = register.PhoneNumber.IsPhoneNomValid();
if (!isPhoneNumberValid)
return new UserResponseDto
{
Status = new StatusMaker().ErrorStatus("Some Error Message")
};
var isActiveAccountPhoneNumberExists = await IsActiveAccountPhoneNumberExist(register.PhoneNumber, cancelationToken);
if (isActiveAccountPhoneNumberExists.Status == "error")
return new UserResponseDto
{
Status = isActiveAccountPhoneNumberExists
};
}
RegisterUser_MustReturnPhoneNumberError is my Test method:
public class AccountUserTests
{
private Mock<IUserService> _userService { get; set; }
public AccountUserTests()
{
_userService = new Mock<IUserService>();
}
public async Task RegisterUser_MustReturnPhoneNumberError()
{
//Arrang
// in here I want to setup IsPhoneNomValid() would return false.
//Act
//Assert
}
}
Is there any way that I can test the static methods which are used in my main function which I am testing ?
Here is the IsPhoneNomValid() codes:
public static class Validation
{
public static bool IsPhoneNomValid(this string phoneNumber)
{
//TODO Does it need to be foreign phone numbers ?
var isMatch = Regex.Match(phoneNumber, #"^09[0-9]{9}$");
if (isMatch.Success)
return true;
return false;
}
}
You want to test your static method IsPhoneNomValid.
[Theory]
[InlineData("123456789")]
public void TestMethod(string phoneNumber)
{
bool isPhoneNumber =Validation.IsPhoneNomValid(phoneNumber);
Assert.True(isPhoneNumber);
}
With InlineData, you can test with multiple phone numbers.
The best option is to use a really invalid phone number in your case. But I have a lib SMock that can do what you want. Here is an example of usage:
public async Task RegisterUser_MustReturnPhoneNumberError()
{
Mock.Setup(context => Validation.IsPhoneNomValid(context.It.IsAny<string>()), async () =>
{
// You must test RegisterUser method in this scope
// Here Validation.IsPhoneNomValid will always return false
var result = await RegisterUser(register, ct);
Assert.AreEqual(expectedStatus, result.Status);
}).Returns(false);
}

I'm getting Http error 404 as a result on working on abp.io framework

I'm new at working on the abp.io framework, precisely Angular + Entity Framework Core.
I want to be able to create or display an objects list of a class that I've created.
For example, I've made a class called Address on the Domain layer.
Here is its AppService on the Application layer:
namespace ASKOM.RefPlusStudio.core.Services
{
[Authorize(corePermissions.Addresses.Default)]
public class AddressAppService : coreAppService, IAddressAppService
{
private readonly IAddressRepository _addressRepository;
private readonly AddressManager _addressManager;
public AddressAppService(IAddressRepository addressRepository, AddressManager addressManager)
{
_addressRepository = addressRepository;
_addressManager = addressManager;
}
[Authorize(corePermissions.Addresses.Create)]
public async Task<AddressDto> CreateAsync(CreateUpdateAddressDto input)
{
var address = await _addressManager.CreateAsync(
input.StreetNumber,
input.StreetName,
input.PostalCode,
input.City,
input.Country
);
await _addressRepository.InsertAsync(address);
return ObjectMapper.Map<Address, AddressDto>(address);
}
[Authorize(corePermissions.Addresses.Delete)]
public async Task DeleteAsync(Guid id)
{
await _addressRepository.DeleteAsync(id);
}
public async Task<AddressDto> GetAsync(Guid id)
{
var address = await _addressRepository.GetAsync(id);
return ObjectMapper.Map<Address, AddressDto>(address);
}
public async Task<PagedResultDto<AddressDto>> GetListAsync(GetAddressListDto input)
{
if (input.Sorting.IsNullOrWhiteSpace())
{
input.Sorting = nameof(Address.Country);
}
var addresses = await _addressRepository.GetListAsync(
input.SkipCount,
input.MaxResultCount,
input.Sorting,
input.Filter
);
var totalCount = await AsyncExecuter.CountAsync(
_addressRepository.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
address => address.Country.Contains(input.Filter)
)
);
return new PagedResultDto<AddressDto>(
totalCount,
ObjectMapper.Map<List<Address>, List<AddressDto>>(addresses)
);
}
[Authorize(corePermissions.Addresses.Edit)]
public async Task UpdateAsync(Guid id, CreateUpdateAddressDto input)
{
var address = await _addressRepository.GetAsync(id);
address.StreetNumber = input.StreetNumber;
address.StreetName = input.StreetName;
address.PostalCode = input.PostalCode;
address.City = input.City;
address.Country = input.Country;
await _addressRepository.UpdateAsync(address);
}
}
}
I gave them all the permissions needed.
Here is corePermissions.cs :
namespace ASKOM.RefPlusStudio.core.Permissions
{
public static class corePermissions
{
public const string GroupName = "core";
//Add your own permission names. Example:
//public const string MyPermission1 = GroupName + ".MyPermission1";
public static class Addresses
{
public const string Default = GroupName + ".Addresses";
public const string Create = Default + ".Create";
public const string Edit = Default + ".Edit";
public const string Delete = Default + ".Delete";
}
}
}
I wanted to see if it can display an Addresses list so I've made a static one on DataSeeder:
namespace ASKOM.RefPlusStudio.core
{
public class coreDataSeederContributor : IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Address, Guid> _addressRepository;
private readonly IGuidGenerator _guidGenerator;
public coreDataSeederContributor(IRepository<Address, Guid> addressRepository, IGuidGenerator guidGenerator)
{
_addressRepository = addressRepository;
_guidGenerator = guidGenerator;
}
public async Task SeedAsync(DataSeedContext context)
{
if (await _addressRepository.GetCountAsync() > 0)
{
return;
}
var address = new Address(
id: _guidGenerator.Create(),
streetNumber: 07,
streetName: "Med Salah Belhaj",
postalCode: 2080,
city: "Ariana",
country: "Tunisie"
);
//autoSave: true
await _addressRepository.InsertAsync(address);
}
}
}
Here is now the result on Swagger UI:
When I try to open the request URL, here is what it shows:
I'm sure that I may have forgotten something and that's why I get Access Denied on the Request URL, but I don't really know what it is because I'm new at this.
Could you please help me?
Thank you
There was a problem with the database. That's why it hasn't read the data I've provided in the DataSeedProvider.

Rhino Mocks - Arg<T> to ommit some parameters

I am using Rhino Mocks to stub out the functionality of a SOAP endpoint and for the most part it works. But, the interface is quite quirky and I am struggling to get the following to work (i have renamed the classes for simplicity)
public interface IWebService
{
void CopyFile(Request request);
}
public interface IService
{
void CopyFile(string filename, byte[] data);
}
public class Request
{
public string Filename { get; set; }
public byte[] Data { get; set; }
}
public class Service : IService
{
IWebService _service;
public Service(IWebService service)
{
_service = service;
}
public void CopyFile(string filename, byte[] data)
{
_service.CopyFile(new Request() {Filename = filename,Data = data });
}
}
Now, in my test I have something like this
[TestCase]
public void TestFileCopyFailsIfFilenameIsMissing()
{
IWebService serviceMock = MockRepository.GenerateMock<IWebService>();
serviceMock.Expect(x => x.CopyFile(Arg<Request>.Is.Equal(new Request() { Filename = Arg<string>.Is.Null, Data = Arg<byte[]>.Is.Anything }))).Throw(new Exception());
Service service = new Service(serviceMock);
service.CopyFile(null, new byte[] { });
}
Which throws the exception:
An exception of type 'System.InvalidOperationException' occurred in Rhino.Mocks.dll but was not handled in user code
Additional information: Use Arg ONLY within a mock method call while recording. 1 arguments expected, 3 have been defined.
I have tried the all possibilities in the world on this one, but cant get it right. If i dont use Arg and use
Expect(null, new byte[]{});
it will always pass no matter what
I suggest to use WhenCalled and in this method check Request object.
bool isCorrectParam = false;
IWebService serviceMock = MockRepository.GenerateMock<IWebService>();
serviceMock.Expect(x => x.CopyFile(null))
.IgnoreArguments()
.WhenCalled(x =>
{
Request req = x.Arguments[0] as Request;
if (req.Data.Count() == 0 && req.Filename == null)
{
isCorrectParam = true;
}
});
Service service = new Service(serviceMock);
service.CopyFile(null, new byte[] { });
Assert.IsTrue(isCorrectParam);
you can also use Matches...
serviceMock.Expect(x => x.CopyFile(Arg<Request>.Matches(r => r.FileName==null))).Throw(new Exception());

How to customize error message of OAuthAuthorizationServerProvider?

We are using the OAuthAuthorizationServerProvider class to do authorization in our ASP.NET Web Api app.
If the provided username and password is invalid in GrantResourceOwnerCredentials, the call
context.SetError( "invalid_grant", "The user name or password is incorrect." );
Produces the following Json result:
{
"error": "invalid_grant",
"error_description": "The user name or password is incorrect."
}
Is there any way to customize this error result?
I would like to make it consistent with default error message format used in other parts of the API:
{
"message": "Some error occurred."
}
Is this possible to achieve with the OAuthAuthorizationServerProvider?
This is how I did it.
string jsonString = "{\"message\": \"Some error occurred.\"}";
// This is just a work around to overcome an unknown internal bug.
// In future releases of Owin, you may remove this.
context.SetError(new string(' ',jsonString.Length-12));
context.Response.StatusCode = 400;
context.Response.Write(jsonString);
+1 for Dasun's answer. Here is how I extended it a bit further.
public class ErrorMessage
{
public ErrorMessage(string message)
{
Message = message;
}
public string Message { get; private set; }
}
public static class ContextHelper
{
public static void SetCustomError(this OAuthGrantResourceOwnerCredentialsContext context, string errorMessage)
{
var json = new ErrorMessage(errorMessage).ToJsonString();
context.SetError(json);
context.Response.Write(json);
}
}
The .ToJsonString() is another extension method that uses the Newtonsoft.Json library.
public static string ToJsonString(this object obj)
{
return JsonConvert.SerializeObject(obj);
}
Usage:
context.SetCustomError("something went wrong");
1+ again for "user2325333" and "Dasun's" answer his solution, your answers are good but still there is an issue .
The Josn Tag still return {error:""}, thus I replace the context.Response.Body with empty MemoryStream
and here the work example
public static class ContextHelper
{
public static void SetCustomError(this OAuthGrantResourceOwnerCredentialsContext context,string error, string errorMessage)
{
var json = new ResponseMessage
{ Data = errorMessage, Message = error, IsError = true }.ToJsonString();
context.SetError(json);
context.Response.Write(json);
Invoke(context);
}
public static string ToJsonString(this object obj)
{
return JsonConvert.SerializeObject(obj);
}
static async Task Invoke(OAuthGrantResourceOwnerCredentialsContext context)
{
var owinResponseStream = new MemoryStream();
var customResponseBody = new System.Net.Http.StringContent(JsonConvert.SerializeObject(new ResponseMessage()));
var customResponseStream = await customResponseBody.ReadAsStreamAsync();
await customResponseStream.CopyToAsync(owinResponseStream);
context.Response.ContentType = "application/json";
context.Response.ContentLength = customResponseStream.Length;
context.Response.Body = owinResponseStream;
}
}
public class ResponseMessage
{
public bool IsError { get; set; }
public string Data { get; set; }
public string Message { get; set; }
}
for usage of this context
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
if (!context.Match.Passcode)
{
context.SetCustomError("invalid_grant", "Passcode is invalid.");
return;
}
}
The Result will be as

Categories

Resources