Override Spock mock with method instead of value - groovy

I know that using Spock I can create a Mock and set a return value on a method e.g.
idpClient.adminCreateUser(_) >> [
user: new UserType()
]
How can I set a method on the Mock so I can customise the value that gets returned? I want to do something like:
idpClient.metaClass.adminCreateUser = { AdminCreateUserRequest adminCreateUserRequest ->
UserType user = new UserType()
user.setUsername(adminCreateUserRequest.getUsername())
AdminCreateUserResult result = new AdminCreateUserResult()
result.setUser(user)
return result
}
Though obviously the above does not work (it returns null). I've looked at the documentation but all I've found is how to return a fixed value (see above).

Maybe you ought to read the Spock manual. There is a section on computing return values. There is no need to use meta classes, the Spock DSL provides syntactical means for stubbing.
I made up this little example for you as an MCVE:
package de.scrum_master.stackoverflow.q64961803;
class UserType {
private String userName;
public void setUserName(String userName) { this.userName = userName; }
public String getUserName() { return userName; }
}
package de.scrum_master.stackoverflow.q64961803;
public class AdminCreateUserResult {
private UserType user;
public void setUser(UserType user) { this.user = user; }
public UserType getUser() { return user; }
}
package de.scrum_master.stackoverflow.q64961803;
public class AdminCreateUserRequest {
private String userName;
public AdminCreateUserRequest(String userName) { this.userName = userName; }
public String getUserName() { return userName; }
}
package de.scrum_master.stackoverflow.q64961803;
public class IDPClient {
public AdminCreateUserResult adminCreateUser(AdminCreateUserRequest adminCreateUserRequest) {
AdminCreateUserResult userResult = new AdminCreateUserResult();
UserType userType = new UserType();
userType.setUserName("real user");
userResult.setUser(userType);
return userResult;
}
}
Shen the corresponding Spock specification would look like this:
package de.scrum_master.stackoverflow.q64961803
import spock.lang.Specification
class IDPClientTest extends Specification {
def test() {
given: "mock IDPClient with stubbed method"
IDPClient idpClient = Mock() {
adminCreateUser(_) >> { AdminCreateUserRequest adminCreateUserRequest ->
UserType user = new UserType()
user.setUserName(adminCreateUserRequest.getUserName())
AdminCreateUserResult result = new AdminCreateUserResult()
result.setUser(user)
result
}
}
def request = new AdminCreateUserRequest("test user")
expect: "real IDPClient behaves normally"
new IDPClient().adminCreateUser(request).user.userName == "real user"
and: "mock IDPClient displays stub behaviour"
idpClient.adminCreateUser(request).user.userName == "test user"
}
}

Related

How to provide CassandraEntityInformation<T, ID> for a SimpleReactiveCassandraRepository?

I'm doing some research bout spring-data-cassandra-reactive and it looks like I can't figure out or find the right documentation about this.
According to the documentation you can create an interface which is annotated with #Repository and then use annotations to create custom queries that will retrieve the data you want. The code would look something like this:
#Repository
public interface UserRepository
extends ReactiveCassandraRepository<UserEntity, UUID>
{
#Query("SELECT u FROM UserEntity u WHERE username = :user ALLOW FILTERING")
Mono<UserEntity> findUserEntityByUsername(#Param("user") String user);
/**
* This is just to illustrate/simulate some custom/advanced logic that cannot be
* done via #Query()
*/
default Mono<UserEntity> saveWithBase64EncodedPassword(UserEntity entity)
{
String encodedPassword = Base64.getEncoder().encodeToString(entity.getPassword().getBytes());
entity.updatePassword(encodedPassword);
return this.save(entity);
}
}
#Table(UserEntity.TABLE_NAME)
public class UserEntity
{
public final static String TABLE_NAME = "users";
#PrimaryKeyColumn(name = "uuid", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
#CassandraType(type = CassandraType.Name.UUID)
#Column
private UUID id;
#Column
#CassandraType(type = CassandraType.Name.VARCHAR)
private String username;
#Column
#CassandraType(type = CassandraType.Name.VARCHAR)
private String password;
public UserEntity()
{
this.id = UUID.randomUUID();
}
public UserEntity(String username, String password)
{
this.id = UUID.randomUUID();
this.username = username;
this.password = password;
}
public UUID getId()
{
return id;
}
public void setId(UUID id)
{
this.id = id;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public void updatePassword(String newPassword)
{
this.password = newPassword;
}
}
Dependencies:
plugins {
id("org.springframework.boot") version "2.6.6"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
}
dependencies {
// Embedded Cassandra Server - used for testing.
implementation("com.github.nosan:embedded-cassandra-spring-boot-starter:4.1.0")
// Spring Data Cassandra Dependencies
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.springframework.boot:spring-boot-starter-data-cassandra-reactive")
testImplementation("org.springframework.boot:spring-boot-starter-test") {
exclude("org.junit.vintage:junit-vintage-engine")
exclude("com.vaadin.external.google:android-json")
}
testImplementation("io.projectreactor:reactor-test")
// /Spring Data Cassandra Dependencies
}
This, so far, works fine. However, I'm trying to figure out how to switch to implementing the interface in order to be able to use #Autowire (i.e. in this example code to autowire
org.springframework.security.crypto.password.PasswordEncoder)
Surfing through the code in the spring-data-cassandra jar I noticed there's a class named org.springframework.data.cassandra.repository.support.SimpleReactiveCassandraRepository which you can extend from. It already has most of the common things you would need implemented for you which is why it looks like the perfect candidate to extend from.
And here comes the problem - it requires CassandraEntityInformation<T, ID> metadata.
I cannot seem to find where this is taken from or how it's supposed to be auto-wired and I feel like I might be missing something or maybe a dependency.
Any ideas?
SimpleReactiveCassandraRepository is a great class as it gives you access to ReactiveCassandraOperations and as such to CqlSession. It is a great way to have fine grained operations. (LWT, Bacthes)
You are correct the different classes would be autowired. Here is a sample code:
#Repository
public class OwnerReactiveCassandraRepository extends SimpleReactiveCassandraRepository<OwnerEntitySpring, UUID> {
protected final CqlSession cqlSession;
protected final ReactiveCassandraOperations reactiveCassandraTemplate;
#SuppressWarnings("unchecked")
public OwnerReactiveCassandraRepository(CqlSession cqlSession, ReactiveCassandraOperations ops) {
super(new MappingCassandraEntityInformation<OwnerEntitySpring, UUID>(
(CassandraPersistentEntity<OwnerEntitySpring>) ops.getConverter().getMappingContext()
.getRequiredPersistentEntity(OwnerEntitySpring.class), ops.getConverter()), ops);
this.cqlSession = cqlSession;
this.reactiveCassandraTemplate = ops;
}
public Flux<OwnerEntitySpring> searchByOwnerName(String ownerLastName) {
return reactiveCassandraTemplate.getReactiveCqlOperations()
.query(SimpleStatement
.builder("SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_LASTNAME + "=?")
.addPositionalValues(ownerLastName)
.build(), (row, rownum) -> new OwnerEntitySpring(row));
}
TLDR; I implemented the Spring PetClinic with Spring data Reactive and you can have access to the full code here It is a step by step workshop with the code. You may want to look specially at this folder
In the project you will find reactive with the drivers only, reactive with CassandraRepositories and reactive with SimpleCassandraRepositories. (Check the TEST folder)

inherited class AutoMapper.AutoMapperMappingException

I am new at automapper and it is a very good stuff easy to use, but now I have a problem with it. Trying to convert my derived class to base and it gives me
AutoMapper.AutoMapperMappingException
Missing type map configuration or unsupported mapping.
Mapping types: ClientEventDb -> EventId
Database.ClientEventDb -> EventId
Destination path: ClientEvent
Source value:
Event:Login
Automapper wants to convert ClientEventDb to EventId? I don't understand why. EventId is an enum...
Please help me I have run out of ideas.
Here is the code which I run:
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.Take(1000).ToArray();
}
Mapper.CreateMap<ClientEventDb, ClientEvent>();
Console.WriteLine("hello");
return edbl.Select(edb => Mapper.Map<ClientEvent>(edb)).ToArray();
Here are my classes
[Table("events", Schema = "public")]
public class ClientEventDb : ClientEvent
{
public ClientEventDb(string userName, EventId happening, object userObject = null)
: base(userName, happening, userObject)
{
}
public ClientEventDb()
{
}
}
[ProtoContract]
[Table("events", Schema = "public")]
public class ClientEvent : ClientEventBase
{
[ProtoMember(1)]
[Column("username")]
public string UserName { get; private set; }
[ProtoMember(2)]
[Column("time")]
public DateTime DateTime { get; private set; }
[ProtoMember(3)]
[Key]
[Column("id")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; private set; }
[ProtoMember(4)]
[Column("data")]
public byte[] UserObject { get; set; }
public ClientEvent(string userName,EventId happening, object userObject=null) : base(happening)
{
UserName = userName;
DateTime = DateTime.Now;
//UserObject = null;
if (userObject!=null) throw new NotImplementedException();
}
public ClientEvent()
{
}
protected ClientEvent Clone()
{
return (ClientEvent)MemberwiseClone();
}
}
[ProtoContract]
[ProtoInclude(10, typeof(ClientEvent))]
public class ClientEventBase
{
[Column("eventid")]
[ProtoMember(1)]
public int EventIdValue { get; set; } //must be public because of entity framework
[NotMapped]
public EventId EventId
{
get { return (EventId) EventIdValue; }
set { EventIdValue = (int) value; }
}
public ClientEventBase(EventId eventId)
{
EventId = eventId;
}
public ClientEventBase()
{
}
public override string ToString()
{
return String.Format("Event:{0}",EventId);
}
}
public enum EventId
{
Login = 1,
Logout,
ExitApplication,
}
UPDATE
bugfix: ClientEvent [Key] attribute moved to id property
Solution was this (thx to stuartd):
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.ToArray();
}
Mapper.CreateMap<ClientEventDb, ClientEvent>().ConstructUsing((ClientEventDb src) => new ClientEvent());
return edbl.Select(Mapper.Map<ClientEvent>).ToArray();
AutoMapper is confused as its made to map between similar properties in different classes, you are using it incorrectly - you just need to go from the derived class to the base which does not require AutoMapper. You could use this to do what you need....
ClientEventDb[] edbl;
using (var context = new DbEntities())
{
edbl=context.Events.Take(1000).ToArray();
}
return edbl.Cast<ClientEvent>().ToList();
I'd be looking at why you even feel you need a derived ClientEventDb though - understand we dont have the whole picture here but it seems to do nothing in addition to what the base class already does.
The issue is that ClientEvent has two constructors but you have not told AutoMapper which to use.
If you want it to use your constructor with parameters, change your mapping code to this and it will work:
Mapper.CreateMap<ClientEventDb, ClientEvent>()
.ConstructUsing(src => new ClientEvent(src.UserName, src.EventId));
Or to make AutoMapper use the default constructor:
Mapper.CreateMap<ClientEventDb, ClientEvent>()
.ConstructUsing((ClientEventDb src) => new ClientEvent());

Custom Function to retrieve data from user table

I want a write a custom function to find a particular property from identity user model.
Say I want to find a user with a specified phone number.
How to do so..???
You need to extend the UserStore class, something like below
public interface IUserCustomStore<TUser> : IUserStore<TUser, string>, IDisposable where TUser : class, Microsoft.AspNet.Identity.IUser<string>
{
Task<TUser> FindByPhoneNumberAsync(string phoneNumber);
}
namespace AspNet.Identity.MyCustomStore
{
public class UserStore<TUser> : Microsoft.AspNet.Identity.EntityFramework.UserStore<TUser>, IUserCustomStore<TUser>
where TUser : Microsoft.AspNet.Identity.EntityFramework.IdentityUser
{
public UserStore(ApplicationDbContext context)
: base(context)
{
}
public Task<TUser> FindByPhoneNumberAsync(string phoneNumber)
{
//Your Implementation
}
}
public class UserStore<TUser> : IUserCustomStore<TUser> where TUser:IdentityUser
{
public virtual Task<TUser> FindByPhoneNumberAsync(string phoneNumber)
{
return _Users.Find(u => u.PhoneNumber == phoneNumber).FirstOrDefaultAsync();
}
}
}
Replace all occurrence of
using Microsoft.AspNet.Identity.EntityFramework
with
using AspNet.Identity.MyCustomStore
And then in the IdentityConfig.cs add a new method to ApplicationUserManager
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
//LEAVE ALL THE METHODS AS IT IS
public virtual Task<ApplicationUser> FindByPhoneNumberUserManagerAsync(string phoneNumber)
{
IUserCustomStore<ApplicationUser> userCustomStore = this.Store as IUserCustomStore<ApplicationUser>;
if (phoneNumber == null)
{
throw new ArgumentNullException("phoneNumber");
}
return userCustomStore.FindByPhoneNumberAsync(phoneNumber);
}
}
You can now call this in the controller like
var user = await UserManager.FindByPhoneNumberUserManagerAsync(model.phoneNumber);
(assuming you have added the phoneNumber property to RegisterViewModel)
Hope this helps.

RhinoMocks AssertWasCalled throws Exception

I am new to TDD and RhinoMocks.
I am trying to test AssertWasCalled but having problems. The constructor to my test is as follows:
public AccountControllerTests()
{
_webAuthenticator = MockRepository.GenerateMock<IWebAuthenticator>();
}
And my test is like this:
[TestMethod]
public void AccountControllerCallsWebAuthenticator_CreateSignInTicketForGoodLoginCredentials()
{
const string username = "good-username";
const string password = "good-password";
var model = new LoginModel { Username = username, Password = password };
_webAuthenticator.Stub(w => w.Authenticate(username, password)).Return(true);
var mockHttpContextBase = MockRepository.GenerateMock<HttpContextBase>();
var accountController = new AccountController(_webAuthenticator);
accountController.Login(model);
_webAuthenticator.AssertWasCalled(x => x.CreateSignInTicket(mockHttpContextBase, username));
}
The error I get is:
Test method Paxium.Music.WebUI.Tests.Controllers.AccountControllerTests.AccountControllerCallsWebAuthenticator_CreateSignInTicketForGoodLoginCredentials threw exception:
Rhino.Mocks.Exceptions.ExpectationViolationException: IWebAuthenticator.CreateSignInTicket(Castle.Proxies.HttpContextBaseProxy7f274f09b6124e6da32d96dc6d3fface, "good-username"); Expected #1, Actual #0.
I have now changed my code as below - Before and after code:
Before:
public class AccountController : Controller
{
private readonly IWebAuthenticator _webAuthenticator;
public AccountController(IWebAuthenticator webAuthenticator)
{
_webAuthenticator = webAuthenticator;
}
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
if (_webAuthenticator.Authenticate(model.Username, model.Password))
{
_webAuthenticator.CreateSignInTicket(HttpContext, model.Username);
return RedirectToAction("Index", "Home");
}
return View(model);
}
return View(model);
}
}
After:
public class AccountController : Controller
{
private readonly IWebAuthenticator _webAuthenticator;
private readonly HttpContextBase _contextBase;
public AccountController()
{
}
public AccountController(IWebAuthenticator webAuthenticator, HttpContextBase contextBase)
{
_webAuthenticator = webAuthenticator;
_contextBase = contextBase;
}
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
if (_webAuthenticator.Authenticate(model.Username, model.Password))
{
_webAuthenticator.CreateSignInTicket(_contextBase, model.Username);
return RedirectToAction("Index", "Home");
}
return View(model);
}
return View(model);
}
}
My tests now pass. How I inject in the contextBase though when my controller is used for real?? I am using StructureMap.
The error message you are receiving indicates that the Assert failed, i.e. the webAuthenticator object was not called with those specific arguments (hence expected #1, actual #0 exception message).
From the limited context you provide, I suspect that the fake instance of the HttpContextBase (mockHttpContextBase) in your test is not the same object that's being passed to the webAuthenticator from your production code.
There's two ways you can go about this: make the assert less strict or make sure the production code uses the fake http context object. If you don't care which instance of HttpContext gets passed to the webAuthenticator in this test, you can use argument matchers (Rhinomocks calls them argument constraints).
In your case, this would turn out something like this:
_webAuthenticator.AssertWasCalled(x => x.CreateSignInTicket(Arg<HttpContextBase>.Is.Anything, Arg<string>.Is.Equal(username)));

Ignore member of base class in YamlDotNet

I have a class which I want to serialize with YamlDotNet:
public class AwesomeClass : PropertyChangedBase
{
private bool _element1;
private bool _enabled;
public bool Element1
{
get { return _element1; }
set
{
_element1 = value;
NotifyOfPropertyChange(() => Element1);
}
}
public bool Enabled
{
get { return _enabled; }
set
{
_enabled = value;
NotifyOfPropertyChange(() => Enabled);
}
}
}
My problem is, in the base class is an element named: IsNotifying
Is there a way to exclude this element from serialization, without the change of the base class?
You could override the property in the derived class and apply the YamlIgnore attribute there. While the sample below works, I suspect for more complicated class hierarchies you would really need to ensure no behavior changes.
public class AwesomeClass : PropertyChangedBase
{
[YamlIgnore]
public new bool IsNotifying
{
get { return base.IsNotifying; }
set { base.IsNotifying = value; }
}
[YamlIgnore]
public override bool Blah
{
get { return base.Blah; }
set { base.Blah = value; }
}
}
public class PropertyChangedBase
{
public bool IsNotifying
{
get;
set;
}
public virtual bool Blah
{
get;
set;
}
}
I had a similar problem (needed to filter properties of a particular type from classes I couldn't change, so using the attribute was not an option) and is what I came up with:
Create a custom type inspector:
public class MyTypeInspector : TypeInspectorSkeleton
{
private readonly ITypeInspector _innerTypeDescriptor;
public MyTypeInspector(ITypeInspector innerTypeDescriptor)
{
_innerTypeDescriptor = innerTypeDescriptor;
}
public override IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container)
{
var props = _innerTypeDescriptor.GetProperties(type, container);
props = props.Where(p => !(p.Type == typeof(Dictionary<string, object>) && p.Name == "extensions"));
props = props.Where(p => p.Name != "operation-id");
return props;
}
}
Create the serializer as follows:
var builder = new SerializerBuilder();
builder.WithTypeInspector(inspector => new MyTypeInspector(inspector));
var serializer = builder.Build();

Resources